Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException
вообще.
См. также: A хороший список лучших практик
Я бы добавил, очень важно, хорошо использовать модификатор final
. Использование "окончательной" модификатор, когда это применимо в Java
Сводка:
final
для обеспечения хорошей инициализации. @NotNull
и @Nullable
if("knownObject".equals(unknownObject)
valueOf()
поверх toString (). StringUtils
StringUtils.isEmpty(null)
. Проливание немного большего количества света, на почему:
LINQ функционален по своей природе. Это используется для запросов результатов возврата и данных. Запрос LINQ не должен изменять состояние приложения (за некоторыми исключениями как кэширование). Поскольку foreach не возвращает результатов, он не имеет многого использования, которое не включает изменение состояния чего-то помимо того, в чем Вы являетесь передающими к нему. И если Вам нужен Foreach () дополнительный метод, это легко к самокрутке.
, Если с другой стороны, то, что Вы хотите, должно взять вход и вызвать функцию на каждом объекте, который возвращает результат, LINQ позволяет через свой избранный метод.
, Например, следующий код называет функцию-делегат на каждом объекте в списке, возвращая true, если тот объект положителен:
static void Main(string[] args)
{
IEnumerable<int> list = new List<int>() { -5, 3, -2, 1, 2, -7 };
IEnumerable<bool> isPositiveList = list.Select<int, bool>(i => i > 0);
foreach (bool isPositive in isPositiveList)
{
Console.WriteLine(isPositive);
}
Console.ReadKey();
}
Метод ForEach на List<T>
делает это. Вы могли перенести свой набор в список и затем использовать тот вызов, но это не действительно хорошая вещь сделать. Похож Вы будете иметь к самокрутке.
Im, слишком сонливый для запоминания, но, в основном.ForEach метод в единственном приложении потока функционально эквивалентен уже существующий foreach оператор. Из того, что я понимаю, основное различие - то, что ForEach мог быть parallized, но это представит нежелательные поведения слишком легко.
На самом деле, фреймворк Reactive Extensions от Microsoft Research действительно добавил эту функциональность.
В сборку System.Interactive
они включили Run()
и Do()
расширения для IEnumerable
.
Do(action) выполнит действие над каждым элементом и вернет его обратно. Это полезно для добавления логирования в запрос linq, например:
var res = GetRandomNumbers(100).Take(10)
.Do(x => Console.WriteLine("Source -> {0}", x))
.Where(x => x % 2 == 0)
.Do(x => Console.WriteLine("Where -> {0}", x))
.OrderBy(x => x)
.Do(x => Console.WriteLine("OrderBy -> {0}", x))
.Select(x => x + 1)
.Do(x => Console.WriteLine("Select -> {0}", x));
В результате получится:
Source -> 96
Where -> 96
Source -> 25
Source -> 8
Where -> 8
Source -> 79
Source -> 25
Source -> 3
Source -> 36
Where -> 36
Source -> 51
Source -> 53
Source -> 81
OrderBy -> 8
Select -> 9
9
OrderBy -> 36
Select -> 37
37
OrderBy -> 96
Select -> 97
97
Run(action) похож на цикл foreach, то есть он складывает последовательность, которая выполняет действие.
Подробнее об этом можно прочитать здесь: http://community.bartdesmet.net/blogs/bart/archive/2009/12/26/more-linq-with-system-interactive-the-ultimate-imperative.aspx
Фреймворк Rx можно найти здесь: http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx