2009-05-04 9 views
32

SingleOrDefault gibt null zurück, aber was, wenn ich Werte zuweisen möchte, um das Objekt zu repräsentieren, das nicht gefunden wurde?SingleOrDefault: Wie können die Standardwerte geändert werden?

+0

Haben Sie eine Antwort gefunden? Sie können den Standard nicht als Versprechen nach Methode ändern. weil SingleOrDefault SingleOrNNull sein sollte, aber es Wertobjekt zurückgeben kann. wer kann zurückgeben 0 für int, ist es Standard oder angebliche Zahl? SingleOrDefault kann 0 zurückgeben, aber es muss nicht Standard sein. gibt null zurück oder nicht. Es ist ein schlechtes Paradigma für OOP. –

Antwort

5

Sie könnten Ihre eigenen rollen.

public static T SingleOrDefault<T>(this IEnumerable<T> enumerable, T defaultValue) { 
    if (1 != enumerable.Count()) { 
    return defaultValue; 
    } 
    return enumerable.Single(); 
} 

Dies kann aber ein bisschen teuer sein, weil Count() erfordert, dass Sie die gesamte Kollektion zu verarbeiten und kann ziemlich teuer sein zu laufen. Es wäre besser, entweder Einzel nennen, die InvalidOperationException fangen oder rollen eine IsSingle Methode

public static bool IsSingle<T>(this IEnumerable<T> enumerable) { 
    using (var e = enumerable.GetEnumerator()) { 
    return e.MoveNext() && !e.MoveNext(); 
    } 
} 

public static T SingleOrDefault<T>(this IEnumerable<T> enumerable, T defaultValue) { 
    if (!enumerable.IsSingle()) { 
    if(enumerable.IsEmpty()) { 
     return defaultValue; 
    } 
    throw new InvalidOperationException("More than one element"); 
    } 
    return enumerable.Single(); 
} 
+1

Dies würde den Standardwert zurückgeben, wenn das Enumerable mehrere Objekte enthält. Sollte es nicht eine Ausnahme wie die Standard-Implementierung auslösen? – tvanfosson

+0

@tvanfosson ja sollte es. Ich hatte den Eindruck, dass SingleOrDefault den Standardwert zurückgeben würde, wenn es etwas anderes als ein Element gäbe. Aber es wird anscheinend nur für keine Elemente tun. Seltsam, ich werde aktualisieren. – JaredPar

52

Sie so etwas wie

myStrings.DefaultIfEmpty("myDefaultString").Single() 

Check-out here

+0

Unterschiedlicher Ansatz +1 – ichiban

+3

+1 für das Unterrichten einer neuen Methode – ajbeaven

0

Sie könnten Ihre eigene Erweiterung erstellen Methoden tun können - Einfach oder Neu.

public static class IEnumerableExtensions 
{ 
    public static T SingleOrNew<T>(this IEnumerable<T> enumeration, T newValue) 
    { 
     T elem = enumeration.SingleOrDefault(); 
     if (elem == null) 
     { 
      return newValue; 
     } 
     return elem; 
    } 

    public static T SingleOrNew<T>(this IEnumerable<T> enumeration, Func<T,bool> predicate, T newValue) 
    { 
     T elem = enumeration.SingleOrDefault(predicate); 
     if (elem == null) 
     { 
      return newValue; 
     } 
     return elem; 
    } 
} 
+3

Das Problem bei diesem Ansatz besteht jedoch darin, dass Sie den newValue-Parameter für eine Auflistung zurückgeben, die ein einzelnes Element mit dem Wert null enthält. Betrachten Sie diesen Ausdruck (new string [] {null}). SingleOrNew ("foo") ;. Es würde fälschlicherweise "foo" – JaredPar

+0

@ JaredPar zurückgeben - ich bin bereit, damit zu leben. Im Allgemeinen setze ich keine Nullen in meine Sammlungen und wenn ich eine solche Methode verwenden sollte, würde ich sie wahrscheinlich sowieso durch meinen Standardwert ersetzen. – tvanfosson

+1

@tvanfosson, das ist eine ziemlich deutliche Bruchänderung gegenüber dem ursprünglichen Algorithmus, die eine heftige Annahme darüber macht, wie Menschen null verwenden. – JaredPar

24

?? operator. Wenn das linke Argument null ist, werte es aus und gebe das zweite Argument zurück.

myCollection.SingleOrDefault() ?? new[]{new Item(...)} 

Dies wird nur mit Referenztypen (oder nullables) arbeiten, aber es täte, was man sehr einfach suchen.

+3

Ein kleiner Applaus klingt in meinem Kopf ab, wenn ich null Koaleszenz benutzen kann. +1 – Stimul8d

+0

@Joe Ich denke, dass das OP tatsächlich den Standardwert ändern möchte, der direkt von SingleOrDefault() zurückgegeben wird, z. Wenn nach einem Person-Objekt gesucht wird und keine existiert, möchte er möglicherweise SingleOrDefault() ein NullPerson-Objekt zurückgeben. Mein Verständnis ist, dass es nicht möglich ist, den Rückgabetyp zu ändern und das Problem muss so gelöst werden, wie Sie es getan haben, aber ich denke, es ist wichtig für das OP zu klären, dass der Standard-Rückgabewert von SingleOrDefault() nicht sein kann geändert. – Matt

Verwandte Themen