Операция DefaultIfEmpty

95

Операции элементов позволяют извлекать элементы из входной последовательности.

Операция 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);
            }
Замена DefaultIfEmpty

В приведенном коде запрос не нашел элемента, эквивалентного "Porshe", поэтому операции First была передана пустая последовательность. Операции First не нравятся пустые последовательности, поэтому она генерирует исключение.

В примере ниже используется тот же самый код, но на этот раз между операциями Where и First вставлена операция DefaultIfEmpty. Таким образом, вместо пустой последовательности операции First будет передана последовательность, содержащая элемент null:

...
string nissan = cars.Where(n => n.Equals("Porshe")).DefaultIfEmpty().First();

Теперь результат выглядит так:

Пример использования DefaultIfEmpty

В примере применения второго прототипа 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);
Использование второго прототипа DefaultIfEmpty
Пройди тесты
Лучший чат для C# программистов