Работа с коллекциями -- одна из самых частых операций при разработке приложений. В этом репозитории я буду публиковать не очевидные моменты, которые мне встретились на практике и которыми хотелось бы поделиться.
Что будет быстрее работать: перебор матрицы int[,]
или зубчатого массива int[][]
аналогичного размера?
Изначально кажется, что перебор будет почти одинаковый, но это не так. Всё зависит как от типа массива, так и от способа перебора.
Матрица является MD-массивом (Multi dimensional array) и реализует только IEnumerable
, но не IEnumerable<T>
, соответственно и не использует IEnumerator<T>
. Поэтому получим упаковку (boxing) во внутренних классах .NET и замедление перебора.
Одномерные массивы с нулевым начальным индексом (Single dimension, zero-based) или SZ-массивы напротив используют обощённые перечислители, например SZGenericArrayEnumerator и перебор по индексам будет быстрее. Также мы можем использовать foreach и LINQ-операции.
Если необходимо быстро обрабатывать именно матрицы, то можно использовать unsafe-перебор по указателю и смещению.
Во сколько раз быстрее?
На матрице 30000*30000 перебор и сумма всех элементов будет будет в 5-6 раз быстрее в пользу одномерных массивов.
Дана бесконечная коллекция элементов, например IEnumerable<string> = new[] { "1", "a", "b", "2", "3" }
. Её необходимо обработать где-то в глубоко вложенных методах и получить коллекцию других элементов, например чисел. Сама типизация может быть на выбор разработчика, но заранее известно, что часть элементов "битые" и при конвертации будут возникать исключения, но необходимо обеспечить дальшнейшее итерирование по исходным данным, а не прерывать процесс.
В данном примере я показываю, как использовать отложенное чтение коллеций через LINQ, оборачивая полученный итератор в простой декоратор, которому дополнительно передается обработчик исключений.
ВАЖНО: Это интересный способ, но подходит не для всех случаев и лучше использовать POCO-объекты result + exception
, где заполнено одно из двух полей.