Какое снижение производительности у List.OfType <>, где весь список такого типа? - PullRequest
3 голосов
/ 25 августа 2011

У меня есть архитектура, в которой мы передаем наши узлы данных как IEnumerable<BaseNode>. Все это прекрасно работает, но в каждом подклассе мы хотим сохранить их как List<AnotherNode>, так как все в этом классе создает и использует AnotherNode объекты (у нас есть около 15 различных подклассов).

Единственное место, где более строго типизированный список не работает, - это метод корневых классов, который возвращает тип IEnumerable<BaseNode> и с ограничениями на ковариацию в .net 3.5, которые не могут быть возвращены. (Мы пока должны оставаться на .net 3.5.)

Но если у меня есть List<AnotherNode> data; и возвращаю data.OfType<BaseNode>(); - это прекрасно работает. Итак, вот мой вопрос.

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

Ответы [ 2 ]

9 голосов
/ 25 августа 2011

Две незначительные вещи:

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

  2. Поскольку результат равен IEnumerable<BaseNode> и уже отфильтрован с помощью функции перечисления с последующим вызовом таких методов, как Count () или ElementAt ()не будет использовать преимущества оптимизации в реализации LINQ для списков.Это также вряд ли будет проблемой, если вы не будете часто использовать эти методы расширения и иметь очень большое количество элементов.

8 голосов
/ 25 августа 2011

Вы видели оператора Cast<T>() Linq?Он должен быть более производительным, чем OfType<T>().

В основном, существует условие, которое выполняется с OfType<T>()

if (item is T) {
    yield return (T)item;
}

Сравните это с тем, что делает Cast<T>():

yield return (T)item;
...