2015-12-29 7 views
3

Рассмотрим следующий пример:Почему вызов Min() в пустом списке ссылок не выбрасывается?

var emptyValueList = new List<int>(); //any value type (long, float, any struct ...) 
var minimum = emptyValueList.Min(); 

Это бросаться InvalidOperationException (последовательность не содержит элементов).

Теперь давайте попробуем с ссылочного типа:

var emptyReferenceList = new List<object>(); //any ref type will do such as object ... 
var minimum = emptyReferenceList.Min(); 

Это не бросает и возвращается null. Это как если бы оператор default был вызван для второго случая, но не для первого. Он также работает для типов с нулевым значением (например, int?, хотя они являются типами значений).

Мне было интересно, почему это так, и если за этим стоит конкретная аргументация?

+0

новый список (); Int? означает, что он является нулевым, вот почему он не сделал никакой ошибки – Se0ng11

+1

Неудовлетворительный ответ, конечно, заключается в том, что это то, что эти функции документированы [to] (https://msdn.microsoft.com/en-us/ library/bb339189 (v = vs.110) .aspx) [do] (https://msdn.microsoft.com/en-us/library/bb341201 (v = vs.110) .aspx) –

ответ

6

Это дизайнерское решение, которое мы должны будем спросить у авторов BCL.

Существуют различные перегрузки Min extension method. Для типов, которые позволяют null, я считаю, Min пропускает все значения null при поиске минимума. Это относится как к ссылочным типам, так и к type Nullable<> (в вашем примере Nullable<int>), который не является ссылочным типом, но который позволяет null (что методы Min решают игнорировать).

Так с ненулевыми структурами, авторы Min, вероятно, думали, что это будет «опасно», чтобы вернуться default(TSource), так что может быть Внушительным (т.е. не нулевой) минимум в других случаях (часто число 0), и следовательно, выход может быть неправильно истолкован.

С типами, которые позволяют null, потому что авторы решили пропустить null значения Поддавшись из источника, можно смело предположить, что null возвращается только в случае, если последовательность не содержит ничего, кроме null ценностей (в том числе при эне пустого источника).


Обратите внимание, что в соответствии со стандартной IComparer<> для обнуляемых типов или ссылочных типов, значение null меньше любого ненулевое значения. Для сортировки алгоритмов (например, используется List<>.Sort) заказ должен быть полным и транзитивным. Таким образом, мы получаем:

Console.WriteLine(
    Comparer<int?>.Default.Compare(null, 7) 
    ); // "-1" 

    Console.WriteLine(
    Nullable.Compare((int?)null, 7) 
    ); // "-1" 


    Console.WriteLine(
    new List<int?> { 9, null, 7, 13, } 
    .OrderBy(ni => ni).First() 
    ); // "" 


    // 'Min' is special in that it disregards 'null' values 
    Console.WriteLine(
    new List<int?> { 9, null, 7, 13, } 
    .Min() 
    ); // "7" 

И Min работает так же, как для истинных ссылочных типов, например System.Version (который является class тип):

var li = new List<Version> { new Version("9.0"), null, new Version("7.0"), new Version("13.0"), }; 

    Console.WriteLine(li.OrderBy(ve => ve).First()); 
    Console.WriteLine(li.Min()); 
+1

Интересно, не удалось знаете, что особое поведение «Мин» (и «Макс», я думаю). Похоже на то, что вы используете соответствующие агрегированные функции sql. –

 Смежные вопросы

  • Нет связанных вопросов^_^