64 Stimmen

Im LINQ alle Werte der Eigenschaft X auswählen, bei denen X != null ist

Gibt es einen kürzeren Weg, um das Folgende zu schreiben? (Etwas, das auf Null überprüft, ohne explizit != null zu schreiben)

from item in list 
where item.MyProperty != null 
select item.MyProperty

11 Stimmen

Gibt es einen Grund, warum du nicht möchtest, dass der Code explizit darüber ist, was er tut?

0 Stimmen

Ich kenne keinen kürzeren Weg. Aber auch Ihre Version gilt allgemein als "lang".

0 Stimmen

Das ist ziemlich einfach. Aber wenn ein einzelnes Element in der Liste null ist, erhalten Sie eine NRE. Ihre where-Klausel muss sein item != null && item.MyProperty != null.

89voto

R. Martinho Fernandes Punkte 217895

Sie können den OfType-Operator verwenden. Er ignoriert Nullwerte in der Ausgangssequenz. Verwenden Sie einfach denselben Typ wie MyProperty und es filtert nichts anderes aus.

// gegeben:
// public T MyProperty { get; }
var nonNullItems = list.Select(x => x.MyProperty).OfType();

Ich würde jedoch davon abraten. Wenn Sie nicht-null Werte auswählen möchten, was kann expliziter sein als zu sagen, dass Sie "die MyProperties aus der Liste, die nicht null sind", möchten?

2 Stimmen

Ich werde auf den Rat aller hören und es so belassen. Aber ich habe Ihre Antwort als akzeptiert markiert, weil Sie mir etwas gesagt haben, das ich nicht wusste.

1 Stimmen

Ich mag diese - sie hält den Code so sauber wie möglich, solange Sie sich daran erinnern können, wie OfType funktioniert! Andernfalls würde ich mit der zweiten Erweiterungsmethode von @CodeInChaos gehen.

70 Stimmen

Missbräuchliches Verwenden von OfType als Null-Prüfung ist unintuitiv und schlechter Stil.

59voto

CodesInChaos Punkte 103089

Sie könnten Ihre eigene Erweiterungsmethode definieren, aber das würde ich nicht empfehlen.

public static IEnumerable SelectNonNull(this IEnumerable sequence,Func projection)
{
   return sequence.Select(projection).Where(e => e != null);
}

Ich mag diese Methode nicht, weil sie zwei Anliegen mischt. Das Projektieren mit Select und das Filtern Ihrer Nullwerte sind separate Operationen und sollten nicht zu einer Methode kombiniert werden.


Ich würde lieber eine Erweiterungsmethode definieren, die nur überprüft, ob das Element nicht null ist:

public static IEnumerable WhereNotNull(this IEnumerable sequence)
{
   return sequence.Where(e => e != null);
}

public static IEnumerable WhereNotNull(this IEnumerable sequence)
    where T : struct
{
   return sequence.Where(e => e != null).Select(e => e.Value);
}

Dies hat nur einen einzigen Zweck, nämlich das Überprüfen auf Null. Bei nullable-Werttypen wird es in den nicht nullable-Äquivalenten umgewandelt, da es sinnlos ist, den nullable-Wrapper für Werte zu erhalten, die nicht null sein können.

Mit dieser Methode wird Ihr Code zu:

list.Select(item => item.MyProperty).WhereNotNull()

0 Stimmen

Ausgenommen, wenn der Ausdrucksbaum benötigt wird (z. B. in Entity Framework).

3 Stimmen

@RicoSuter Wenn Sie das unterstützen müssen, fügen Sie eine Überladung von IQueryable hinzu.

16voto

Anthony Punkte 9225

Ich neige dazu, eine statische Klasse mit grundlegenden Funktionen für Fälle wie diese zu erstellen. Sie ermöglichen es mir, Ausdrücke wie

var myValues myItems.Select(x => x.Value).Where(Predicates.IsNotNull);

Und die Sammlung von Prädikatsfunktionen:

public static class Predicates
{
    public static bool IsNull(T value) where T : class
    {
        return value == null;
    }

    public static bool IsNotNull(T value) where T : class
    {
        return value != null;
    }

    public static bool IsNull(T? nullableValue) where T : struct
    {
        return !nullableValue.HasValue;
    }

    public static bool IsNotNull(T? nullableValue) where T : struct
    {
        return nullableValue.HasValue;
    }

    public static bool HasValue(T? nullableValue) where T : struct
    {
        return nullableValue.HasValue;
    }

    public static bool HasNoValue(T? nullableValue) where T : struct
    {
        return !nullableValue.HasValue;
    }
}

10 Stimmen

Bei Verwendung dieser Methode habe ich die Klasse in Is umbenannt und das Is-Präfix aus allen Methoden entfernt. Meiner Meinung nach macht es die Dinge lesbarer: collection.Where(Is.NotNull).Select...

0 Stimmen

Nur froh, dass ich jemandem helfen konnte!

0 Stimmen

Es ist besser, für generische Typen nicht die Operatoren == und != zu verwenden. Denn diese können überschrieben sein im Typ. Verwenden Sie ReferenceEquals(value, null)

4voto

abatishchev Punkte 94886

Es besteht keine Möglichkeit, einen Check zu überspringen, wenn er existiert.

4voto

Vlad Bezden Punkte 71128

// Wenn Sie überprüfen müssen, ob MyProperty aller Elemente nicht null ist

if (list.All(x => x.MyProperty != null))
// do something

// oder wenn Sie überprüfen müssen, ob mindestens ein Elementeigenschaft nicht null ist

if (list.Any(x => x.MyProperty != null))
// do something

Sie müssen jedoch immer auf null überprüfen

0 Stimmen

Das ist für mich die richtige Antwort. Vielleicht waren meine Anforderungen anders als die der Person, die die Frage gestellt hat, aber für mich hat das perfekt funktioniert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X