Ich weiß, dass in der Regel leere Liste mehr als NULL ist. Aber ich werde NULL zurückgeben, hauptsächlich aus zwei Gründen
??
-Operation auszuführen, um einen Rückgabewert zu erhalten.Für Strings haben wir IsNullOrEmpty. Gibt es irgendetwas, das von C # selbst für List oder IEnumerable tut?
nichts in das Framework eingebettet, aber es ist eine ziemlich einfache Erweiterungsmethode.
/// <summary>
/// Determines whether the collection is null or contains no elements.
/// </summary>
/// <typeparam name="T">The IEnumerable type.</typeparam>
/// <param name="enumerable">The enumerable, which may be null or empty.</param>
/// <returns>
/// <c>true</c> if the IEnumerable is null or empty; otherwise, <c>false</c>.
/// </returns>
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
if (enumerable == null)
{
return true;
}
/* If this is a list, use the Count property for efficiency.
* The Count property is O(1) while IEnumerable.Count() is O(N). */
var collection = enumerable as ICollection<T>;
if (collection != null)
{
return collection.Count < 1;
}
return !enumerable.Any();
}
Daniel Vaughan führt den zusätzlichen Schritt des Castings aus Performancegründen zu ICollection (wo möglich). Etwas, an das ich nicht gedacht hätte.
Late update: seit C # 6.0 kann der null-propagation-Operator verwendet werden, um eine kurze Aussage wie folgt auszudrücken:
if (enumerable?.Any() ?? false)
Anmerkung 1:?? false
ist aus folgendem Grund erforderlich (Zusammenfassung/Zitat aus diesem Beitrag ):
Der
?.
-Operator gibtnull
zurück, wenn ein untergeordnetes Mitgliednull
..__ ist. Aber [...] wenn wir versuchen, ein Nicht-Nullable
-Mitglied zu bekommen, wie dasAny()
-Methode, diebool
[...] zurückgibt, wird der Compiler "wrap" einen Rückgabewert inNullable<>
. Zum Beispiel wirdObject?.Any()
gib unsbool?
(wasNullable<bool>
ist), nichtbool
. [...] Da es nicht implizit inbool
umgewandelt werden kann, kann dieser Ausdruck nicht inif
verwendet werden.
Anmerkung 2: als Bonus, die Aussage ist auch "threadsicher" (Zitat aus Antwort von dieser Frage ):
Wenn in einem Multithread-Kontext auf [Enumerable] von einem anderen .__ aus zugegriffen werden kann. thread (entweder weil es ein Feld ist, auf das zugegriffen werden kann, oder weil es in einem Lambda, das einem anderen Thread ausgesetzt ist, geschlossen ist .__). Wert kann bei jeder Berechnung anders sein [d. h. vordere Nullprüfung]
Es ist nichts eingebaut.
Es ist jedoch eine einfache Erweiterungsmethode:
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
if(enumerable == null)
return true;
return !enumerable.Any();
}
var nullOrEmpty = list == null || !list.Any();
Die vorherigen Antworten zu einer einfachen Erweiterungsmethode für C # 6.0+ zusammenfassen:
public static bool IsNullOrEmpty<T>(this IEnumerable<T> me) => !me?.Any() ?? true;
Wie alle anderen gesagt haben, ist nichts in das Framework eingebaut, aber wenn Sie Castle verwenden, dann hat Castle.Core.Internal es.
using Castle.Core.Internal;
namespace PhoneNumbers
{
public class PhoneNumberService : IPhoneNumberService
{
public void ConsolidateNumbers(Account accountRequest)
{
if (accountRequest.Addresses.IsNullOrEmpty()) // Addresses is List<T>
{
return;
}
...
Wenn Sie alle Elemente abrufen müssen, falls sie nicht leer sind, funktionieren einige der Antworten hier nicht, da der Aufruf von Any()
auf einer nicht rücklauffähigen Aufzählungskomponente ein Element "vergisst".
Sie könnten einen anderen Ansatz wählen und Nullen in Leergut verwandeln:
bool didSomething = false;
foreach(var element in someEnumeration ?? Enumerable.Empty<MyType>())
{
//some sensible thing to do on element...
didSomething = true;
}
if(!didSomething)
{
//handle the fact that it was null or empty (without caring which).
}
Ebenso kann (someEnumeration ?? Enumerable.Empty<MyType>()).ToList()
etc. verwendet werden.
var nullOrEmpty = !( list?.Count > 0 );
für mich ist die beste isNullOrEmpty-Methode so
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
return !enumerable?.Any() ?? true;
}
Ich habe den Vorschlag von Matthew Vines geändert, um das "Mögliche mehrfache Aufzählen von IEnumerable" zu vermeiden. (Siehe auch den Kommentar von Jon Hanna)
public static bool IsNullOrEmpty(this IEnumerable items)
=> items == null
|| (items as ICollection)?.Count == 0
|| !items.GetEnumerator().MoveNext();
... und der Unit-Test:
[Test]
public void TestEnumerableEx()
{
List<int> list = null;
Assert.IsTrue(list.IsNullOrEmpty());
list = new List<int>();
Assert.IsTrue(list.IsNullOrEmpty());
list.AddRange(new []{1, 2, 3});
Assert.IsFalse(list.IsNullOrEmpty());
var enumerator = list.GetEnumerator();
for(var i = 1; i <= list.Count; i++)
{
Assert.IsFalse(list.IsNullOrEmpty());
Assert.IsTrue(enumerator.MoveNext());
Assert.AreEqual(i, enumerator.Current);
}
Assert.IsFalse(list.IsNullOrEmpty());
Assert.IsFalse(enumerator.MoveNext());
}