2015-07-01 2 views
5

Wenn mit leeren Sequenzen zu tun, ich war überrascht zu erfahren, dass das Verhalten für min oder max unterschiedlich ist, je nachdem, ob die Quellensammlung Elemente sind von value type oder von reference type:Warum ist Enumerable Min oder Max zwischen Sammlungen von Referenz- und Werttypen inkonsistent?

var refCollection = new object[0]; 
var valCollection = new int[0]; 
var nullableCollection = new int?[0]; 

var refMin = refCollection.Min(x => x); // null 
var valMin = valCollection.Min(); // InvalidOperationException 
var nullableMin = nullableCollection.Min(); // null 

Dieser Unterschied von Verhaltensweisen ist schön auf .NET Core implementation of Enumerable extensions zu sehen.

Dies ist jedoch nicht der Fall, wenn man zum Beispiel Jon Skeet's MinBy extension betrachtet, die auf jeden Fall wirft, wie ich es erwartet hätte.

Führt der Unterschied in den Verhaltensweisen nicht zu Verwirrungen? Gibt es einen Vorteil für die Rückgabe von null Sammlungen von Ref-Typen?

+1

Nur der Vollständigkeit halber, fügen Sie einen Fall 'var nullableCollection = new int? [0];' – xanatos

+0

Guter Punkt! Ein NULL-fähiger Fall wurde hinzugefügt. –

+0

Ich möchte auch wissen, warum '(neues Objekt [0]). Min()' gibt 'null' und' (new int [0]). Min() 'wirft plötzlich' InvalidOperationException' ([Beweis] (https://ideone.com/9NDIob)). @ JonSkeet Antwort antwortet nicht wirklich * warum * Verhalten ist anders. – Sinatr

Antwort

8

Es lohnt bedenkt, dass Typen (beide NULL festlegbare Werttypen und Referenztypen) verhalten sich unterschiedlich auf Nicht-Nullable-Wertetypen in der Regel auf NULL festlegbare, wenn es um Min kommt: ein null Wert als „fehlend“ im Allgemeinen behandelt wird, so es ist nicht unvernünftig, dass das "Minimum der nur fehlenden Werte" "der fehlende Wert" ist.

Zum Beispiel:

int?[] nullableInts = new int?[5]; // All values null 
int? min = nullableInts.Min(); // No exception, min is null 
nullableInts[3] = 2; 
min = nullableInts.Min(); // No exception, min is 2 

Für Nicht-Nullable-Wertetypen, gibt es wirklich nicht die Möglichkeit, was einen „fehlenden Wert“ (es sei denn, der Rückgabetyp immer verändert wurde ein Nullable Type sein), daher die Ausnahme ... aber das ist ziemlich leicht zu erkennen, wie bei einem nicht-nullbaren Werttyp, die einzige Situation, in der es kein Minimum gibt, ist wenn die Quelle leer ist.

(Es ist möglich, dass MinBy soll eigentlich die gleiche Art und Weise verhalten :)

Dies ist auch bei den Umwandlungen in LINQ to XML konsistent:

XElement element = null; 
int? x = (int?) element; // null 
int y = (int) element; // Bang 

Grundsätzlich ist es ein gewisses Maß an Sinn machen - Keine Option wäre mit allem vereinbar.

+3

Ich würde hinzufügen, dass die Funktion von 'Min()' ist konsistent mit der Funktion von SQL 'MIN()' ... Die 'MIN()' einer leeren Menge ist 'NULL'. Offensichtlich kann ein nicht nullbarer Werttyp nicht 'NULL' enthalten. Also die Ausnahme. – xanatos

+0

Konsistenz mit SQL-Verhalten scheint wie ein sehr wichtiger Punkt. –