Разные способы перечисления коллекции - PullRequest
3 голосов
/ 29 декабря 2010

Из приведенных ниже двух способов перечисления коллекции, если один из них предпочтительнее другого, ИЛИ оба одинаковы с точки зрения производительности (т. Е. Поскольку преобразование ToList () используется во втором подходе)

foreach(SomeType st in Collection)
{
   //Do something
}


Collection.OfType<SomeType>.ToList().ForEach()

Есть ли другой способ (кроме использования переизбрания)?

РЕДАКТИРОВАТЬ

Как насчет этого сценария?

class SomeType : IMyType
{
}

class OtherType : IMyType
{
}

class SomeCollection<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable
{
}

Учитывая, что MyTypes являетсясвойство в классе с типом SomeCollection<IMyType> Подходящие ниже 2 подходят одинаково?

foreach(IMyType mt in MyTypes) 
{   
  if(IMyType is SomeType)
  return; 
}

ИЛИ

if(MyTypes.OfType<SomeType>.Any())
    return;

Ответы [ 6 ]

3 голосов
/ 29 декабря 2010

Из тех, что вы упомянули, первое предпочтительнее. Второй будет делать гораздо больше, включая преобразование в список и проверку типа, чтобы в конце концов все равно выполнить foreach.

Конечно, есть и другие способы итерации, но они зависят от коллекции. Для IList реализаций и массивов вы можете использовать обычный цикл for и индексировать элементы, используя myitem[i].

Но нет причин не использовать foreach, поскольку он работает для всех коллекций и всегда является наиболее оптимальным выбором с точки зрения производительности. Под оптимальным я имею в виду сложность алгоритма / big-o

РЕДАКТИРОВАТЬ в ответ на ваш вопрос edit В общем, вы должны использовать схему перечисления, которая обеспечивает лучшую читаемость (без серьезного влияния на производительность). В вашем примере, где вы хотите увидеть, есть ли в вашем списке какие-либо элементы определенного типа, я бы пошел с маршрутом LINQ (collection.OfType...). В нем четко выражено намерение, и почти можно прочитать текст на английском языке и получить значение: «В моей коллекции найдите элементы типа X и скажите, есть ли они».

3 голосов
/ 29 декабря 2010

Конечно, с индексируемыми коллекциями вы можете использовать классический цикл for:

for( int i = 0; i < collection.Count; i++ )
{
    collection[i] ... // do something with the item
}

Вы также можете напрямую получить доступ к объекту IEnumerator (для которого foreach является синтаксическим сахаром):

using( IEnumerator<YourType> e = collection.GetEnumerator() )
{
    while( e.MoveNext() )
    {
        // do something with the item
        e.Current ...
    }
}

Все различные подходы для перечисления коллекции полезны в некоторых конкретных случаях - но это очень контекстуально относительно того, какой шаблон использовать, где.

Например, использование объекта IEnumerator напрямую полезно, когда требуется точный контроль над тем, как и когда увеличивать и обращаться к итератору. Многие операторы LINQ внутренне используют IEnumerator для оптимизации своей реализации.

Разумное правило: что при посещении предметов для создания побочных эффектов вы должны использовать for или foreach, когда преобразуете (проецируете) одну последовательность в другую Вы должны использовать LINQ (Выбрать, Где и т. д ...). Использование LINQ подчеркивает результат, скрывая механизм, тогда как циклы подчеркивают механизм.

1 голос
/ 29 декабря 2010

Есть параллель. Для каждого:

http://msdn.microsoft.com/en-us/library/dd460720.aspx

0 голосов
/ 29 декабря 2010

Для некоторых типов коллекций (например, List (Of T)) перечисление с помощью классического foreach выполняется намного быстрее. Это потому, что конструкция foreach в C # не использует IEnumerator и IEnumerable напрямую.

Вызывает метод GetEnumerator (), затем вызывает MoveNext () и текущий объект возвращается. Так как List возвращает структуру ListEnumerator, методы которого быстрее, когда они вызываются напрямую, иначе - через интерфейс IEnumerator.

0 голосов
/ 29 декабря 2010

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

0 голосов
/ 29 декабря 2010

Очевидно, что не преобразование коллекции будет быстрее, чем преобразование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...