Эффективно ли преобразование этого ArrayList в общий список?

Код, который я пишу, получает ArrayList из неуправляемого кода, и этот ArrayList всегда будет содержать один или несколько объектов типа Grid_Heading_Blk. Я рассматривал возможность замены этого ArrayList на универсальный список, но я не уверен, что операция преобразования будет настолько дорогостоящей, чтобы свести на нет преимущества работы с общим списком. В настоящее время я просто запускаю операцию foreach (Grid_Heading_Blk in myArrayList) для работы с содержимым ArrayList после передачи ArrayList классу, который будет его использовать.

Должен ли я преобразовать ArrayList в общий типизированный список? И если да, то какой самый эффективный способ сделать это?


person Greg    schedule 07.06.2010    source источник


Ответы (7)


Вот пример эффективного способа создания универсального списка из ArrayList.

List<Grid_Heading_Blk> myList = new List<Grid_Heading_Blk>(source.Count);
myList.AddRange(source.OfType<Grid_Heading_Blk>());

При вызове конструктора, который принимает целое число, резервное хранилище выделяется только один раз.

Как всегда, вы должны измерять производительность, используя те инструменты, которые вы обычно используете.

person Amy B    schedule 08.06.2010
comment
Спасибо всем. Здесь много хороших ответов. Хотя производительность/эффективность, безусловно, является ключевым вопросом, возможно, я недооценивал читабельность, обеспечиваемую типизированной структурой. Если кто-то другой со временем будет поддерживать мой код, я хочу, чтобы было как можно понятнее, что я делаю. - person Greg; 08.06.2010

Я часто использую этот контрольный список для оценки вопросов, подобных вашему:

  1. Сделайте это правильно
  2. Уточни
  3. Сделайте это кратким
  4. Сделайте это эффективным

List<Grid_Heading_Blk> намного лучше раскрывает намерения, чем ArrayList. Так что, даже не считаясь с эффективностью, уже есть большой выигрыш по пункту 2.

Чтобы преобразовать ArrayList в List<>, вы должны выполнить итерацию по ArrayList один раз и привести каждый элемент. foreach выполняет неявное приведение, поэтому накладные расходы связаны только с дополнительной итерацией.

Повторение последовательности дважды увеличивает производительность с O(n) до O(2n), которая по-прежнему равна O(n) (для производительности важна величина, а не значение). Таким образом, вы можете считать изменение доброкачественным.

Однако, если буквально все, что вы делаете, это запускаете foreach, вам следует просто использовать ArrayList напрямую — изменение его на List<> не даст вам больше выразительной силы.

person Bryan Watts    schedule 07.06.2010

Зачем вообще нужно конвертировать ArrayList? Честно говоря, кажется, что ваш цикл foreach поможет. Да, как сказал Кевин выше, единственный штраф, который вы заплатите, — это распаковка, но в нынешнем виде это довольно простой код, и у вас, вероятно, недостаточно заголовков сетки, чтобы заплатить реальный удар по производительности.

Но если вы должны преобразовать его, я бы сказал, вместо того, чтобы писать свой собственный цикл for для преобразования в общий тип List, может быть лучше использовать конструктор, который принимает тип IEnumerable (что-то ArrayList должно уже реализовываться).

List<Grid_Heading_Blk> heading = new List<Grid_Heading_Blk>( arrayList );
person WalterVonBruegemon    schedule 08.06.2010

Самый большой штраф за использование ArrayLists — это бокс.

С дженериками вы получаете:
1. Безопасность во время компиляции
2. Расширения дженериков
3. Устранение этого ограничения, связанного с преобразованием всего в списке в объект типа.

Это преимущества, которые вы получаете, используя их. Это преимущество, но если вам нужно повторно заполнить общий список из ArrayList, возможно, это не стоит делать, особенно если вы просто просматриваете список, чтобы получить объекты.

person kemiller2002    schedule 07.06.2010

«Эффективность» — это не свойство «или-или». Это относительно, так же как большая мышь, вероятно, не больше маленького слона.

Это зависит от того, что еще вы делаете.

Ваш пробег может варьироваться, но по моему опыту, хотя ArrayList может быть "медленнее", чем List<T>, я никогда не делал так мало, чтобы это было хоть как-то заметно.

Тем не менее, приятно, когда компилятор выполняет проверку типов за меня, и приятно, что мне не нужно приводить типы.

person Mike Dunlavey    schedule 07.06.2010

Если объекты поступают из неуправляемого кода и вам не нужно добавлять или удалять объекты, то массив Grid_Heading_Blk может быть более эффективным, чем список. Если вы можете избежать использования массива, использование цикла for может быть немного быстрее, чем foreach.

person bbudge    schedule 08.06.2010

Вы можете отфильтровать все элементы arrayList, которые могут быть приведены к одному и тому же типу, используя Enumerable.OfType Метод (из TResult)

List<MyClass> typedList = arrayList.OfType<MyClass>().ToList();

(на основе предложения в http://www.codeproject.com/Tips/68291/Convert-ArrayList-to-a-Generic-List )

person Michael Freidgeim    schedule 21.10.2011