Операция DefaultIfEmpty
95LINQ --- LINQ to Objects --- Операция DefaultIfEmpty
Операции элементов позволяют извлекать элементы из входной последовательности.
Операция DefaultIfEmpty возвращает последовательность, содержащую элемент по умолчанию, если входная последовательность пуста. У операции DefaultIfEmpty есть два прототипа, которые описаны ниже:
- Первый прототип DefaultIfEmpty
-
public static IEnumerable<T> DefaultIfEmpty<T>( this IEnumerable<T> source);
Этот прототип операции DefaultIfEmpty возвращает объект, который при перечислении входной последовательности source выдает каждый ее элемент, если только последовательность не окажется пустой — тогда возвращается последовательность из одного элемента default (Т). Для ссылочных и допускающих null типов значением по умолчанию является null.
Обратите внимание, что в отличие от всех прочих операций типа элементов, DefaultIfEmpty возвращает последовательность типа IEnumerable<T> вместо самого типа Т. Существуют еще дополнительные операции типа элементов, но они не включены в эту статью, поскольку не являются отложенными.
- Второй прототип DefaultIfEmpty
Второй прототип позволяет указать значение по умолчанию.
public static IEnumerable<T> DefaultIfEmpty<T>( this IEnumerable<T> source, T defaultValue);
Эта операция полезна для всех других операций, которые генерируют исключения в случае пустой входной последовательности. Вдобавок эта операция удобна в сочетании с операцией GroupJoin для производства левосторонних внешних соединений (left outer joins).
Ниже показан пример прототипа DefaultIfEmpty с пустой последовательностью. В данном примере не применяется операция DefaultIfEmpty, чтобы посмотреть, что происходит. Производится поиск в массиве Cars названия Porshe, возвращается первый элемент, и если он не будет равен null, выводится сообщение:
string[] cars = { "Alfa Romeo", "Aston Martin", "Audi", "Nissan", "Chevrolet", "Chrysler", "Dodge", "BMW",
"Ferrari", "Bentley", "Ford", "Lexus", "Mercedes", "Toyota", "Volvo", "Subaru", "Жигули :)"};
try
{
string nissan = cars.Where(n => n.Equals("Porshe")).First();
if (nissan != null)
Console.WriteLine("Автомобиль Porshe найден");
else
Console.WriteLine("Автомобиль Porshe не найден");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}

В приведенном коде запрос не нашел элемента, эквивалентного "Porshe", поэтому операции First была передана пустая последовательность. Операции First не нравятся пустые последовательности, поэтому она генерирует исключение.
В примере ниже используется тот же самый код, но на этот раз между операциями Where и First вставлена операция DefaultIfEmpty. Таким образом, вместо пустой последовательности операции First будет передана последовательность, содержащая элемент null:
...
string nissan = cars.Where(n => n.Equals("Porshe")).DefaultIfEmpty().First();
Теперь результат выглядит так:

В примере применения второго прототипа DefaultIfEmpty, приведенном ниже, разрешено указывать значение по умолчанию для пустой последовательности:
string[] cars = { "Alfa Romeo", "Aston Martin", "Audi", "Nissan", "Chevrolet", "Chrysler", "Dodge", "BMW",
"Ferrari", "Bentley", "Ford", "Lexus", "Mercedes", "Toyota", "Volvo", "Subaru", "Жигули :)"};
string porshe = cars
.Where(n => n.Equals("Porshe"))
.DefaultIfEmpty("Не найдено :(")
.First();
Console.WriteLine(porshe);
