it-swarm.com.de

Optimale Möglichkeit, bedingte Nulloperatoren in booleschen Ausdrücken zu verwenden

Sie schreiben einen booleschen Ausdruck, der folgendermaßen aussehen könnte:

team.Category == "A Team" && team?.Manager?.IsVietnamVet

public class Manager
{
    public bool IsVietnamVet { get; set; }
}

public class Team
{
    public string Category { get; set; }

    public Manager Manager { get; set; }
}

... und Sie erhalten eine Fehlermeldung:

Der Operator '&&' kann nicht auf Operanden vom Typ 'bool' und 'bool?'

Was ist der optimale/sauberste Weg, um damit umzugehen?

  1. team.Category == "A Team" && (team?.Manager?.IsVietnamVet ?? false)

    Ist das wirklich lesbar?

  2. team.Category == "A Team" && (team?.Manager?.IsVietnamVet).GetValueOrDefault()

    In LINQ-to-Entities funktioniert es möglicherweise nicht ...

  3. team.Category == "A Team" && team?.Manager?.IsVietnamVet == true

    Würden Sie wirklich if (condition == true) ohne zu zögern schreiben?

Gibt es noch andere Möglichkeiten? Ist es letztendlich besser zu schreiben:

  1. team.Category == "A Team" && team.Manager != null && team.Manager.IsVietnamVet
11
Santhos

In diesem speziellen Fall kann es ratsam sein, dem Gesetz von Demeter zu folgen, d.h.

public class Team
{
    public bool IsManagerVietnamVet => Manager?.IsVietnamVet ?? false;
}    

Wenn ein boolescher Ausdruck komplex oder hässlich ist, gibt es nichts zu sagen, dass Sie ihn (oder einen Teil davon) nicht in eine separate Anweisung aufteilen können:

bool isVietnamVet = Manager?.IsVietnamVet ?? false;

if (team.Category == "A Team" && isVietnamVet)

Wenn Sie den Code im Debugger durchgehen, ist es oft besser, ausgefeilte Bedingungen in einem einzigen bool zu packen, um ein wenig Mouseover-Hovering zu sparen. In der Tat könnte es einfacher sein, das Ganze in eine bool -Variable zu setzen.

bool isVietnamVetAndCategoryA = (team.Category == "A Team"
    && Manager?.IsVietnamVet ?? false);

if (isVietnamVetAndCategoryA)

oder mit LINQ:

var wibble = from flight in airport
             from passenger in flight.manifest
             let isOnPlane = 
                 (flight.FinishedBoarding && passenger.Flight == flight.FlightNumber)
             where !isOnPlane
             select passenger;
4
Ben Cottrell

Ich denke Option 3 (d. H. == true) ist der sauberste Weg, um zu testen, dass ein bool? ist true, weil es sehr klar ist, was es tut.

In den meisten Code x == true macht keinen Sinn, weil es das gleiche ist wie x, aber das gilt hier nicht, also denke ich == true wäre nicht sehr verwirrend.

3
svick

Wenn Sie die Antwort von Ben Cottrell erweitern, kann Ihnen das Muster "Null Object" weiterhelfen.

Anstatt ein null Team/Manager zurückzugeben, extrahieren Sie die Schnittstellen ITeam und IManager und geben Sie sinnvolle alternative Implementierungen zurück:

public class NoManager : IManager
{
    public bool IsVietnamVet => false;
}

public class NoTeam : ITeam
{
    public bool ManagedByVietnamVet => false;

    public IManager Manager => new NoManager();
}

Dann können Sie plötzlich team.ManagedByVietnamVet sicher.

Dies setzt natürlich voraus, dass der Upstream-Anbieter von team null-sicher ist - dies kann jedoch durch entsprechende Tests sichergestellt werden.

3
Ant P