2009-11-12 1 views
0

Вероятно, вопрос о типизации (в C++ с STL все будет сделано через std :: vector и не возникнет вопросов).C#: Как получить доступ к структурам в ArrayList?

У меня есть ArrayList, и я хотел бы сохранить там некоторые структуры. Как

struct txtRange 
    { 
     public String sText; 
     public String sTag; 
     public int iBeg; 
     public int iEnd; 
    }; 

    ArrayList Ranges = new ArrayList(); 

    txtRange iRange; 
    iRange.sText = entityText; 
    iRange.sTag = ""; 
    iRange.iBeg = Ranges.Count > 0 ? Ranges[Ranges.Count - 1].iEnd + 1 : 0; 
    iRange.iEnd = iRange.iBeg + tmpstr.Length; 
    Ranges.Add(iRange); 

На самом деле, у меня есть проблемы при доступе к Ranges [Ranges.Count - 1] .iEnd: 'объект' не содержит определения для 'iEnd'. Как должен быть создан ArrayList указанного типа?

Аналогичный вопрос (How to cast object/structure into arraylist?) заставил меня немного посмеяться ... Но все же есть объяснение, как добавить структуры в ArrayList, но не как получить значения оттуда.

+0

«в C++ с STL все будет сделано через std :: vector, и вопросов не возникнет» - проверьте список (в System.Collections.Generic). Вы можете поместить в него структуры без кастингов, бокса и распаковки. Если вам действительно не нужна гетерогенная коллекция, это гораздо лучший выбор, чем ArrayList. – itowlson

ответ

2

Как я вижу, вам просто нужно вывести выход.

((txtRange)Ranges[Ranges.Count-1]).iEnd 

Или используйте List<txtRange> вместо этого для строго типизированного любящего.

5

У вас есть три проблем здесь:

  1. Вы используете изменяемые структуры. С этой плохой идеей. Почему не txtRange класс?

  2. Вы используете общедоступные поля - без инкапсуляции.

  3. Вы используете не общий тип ArrayList, что означает, что все становится коробкой, и у вас только слабый ввод.

Вы можете привести результат, как вы удалите его, но если вы хотите изменить содержание, вы должны положить его обратно (потому что это структура, и копируется каждый раз). Фрагмент, который вы указали, на самом деле не нуждается в изменении чего-либо, но вы, вероятно, столкнетесь с ним в какой-то момент. Вот фрагмент кода в рабочем коде:

txtRange iRange; 
iRange.sText = entityText; 
iRange.sTag = ""; 
iRange.iBeg = Ranges.Count > 0 ? ((txtRange) Ranges[Ranges.Count - 1]).iEnd + 1 
           : 0; 
iRange.iEnd = iRange.iBeg + tmpstr.Length; 
Ranges.Add(iRange); 

Однако, я хотел бы предложить:

  • Переименовать txtRange в TextRange
  • Использовать общий List<T> вместо ArrayList, если каким-то образом вы работаете на платформе, не поддерживает дженерики (микрофрейм или .NET 1.1)
  • Либо сделать TextRange i mmutable, или сделать его класс - или, возможно, оба
  • Используйте свойства вместо открытых полей (см here по многим причинам)
  • Избегайте использования сокращений, и я бы лично канавы «я» префикс (я бы использовать Start , Тег, конец, текст)
+1

Мне было любопытно, почему изменчивые структуры плохие, и для тех, кто также задается вопросом, вот ответ, который я нашел: http://blogs.msdn.com/ericlippert/archive/2008/05/14/mutating-readonly-structs.aspx –

0

Прежде чем вы сможете получить доступ к его свойствам, вы должны перенести его в тип txtRange.

Или вы всегда можете пойти List<T> где Т txtRange маршрут, как будет работать без литья

0
iRange.iBeg = Ranges.Count > 0 ? ((txtRange)Ranges[Ranges.Count - 1]).iEnd + 1 : 0; 
0

Спасибо, проблема может и быть решена путем явного приведения как

iRange.iBeg = Ranges.Count > 0 ? ((txtRange)Ranges[Ranges.Count - 1]).iEnd + 1 : 0; 

или используя дженерики.

Смежные вопросы