Frage

Ich versuche, den bedingten Operator zu verwenden, aber ich bin immer hing von der Art bis es denkt, soll das Ergebnis sein.

Im Folgenden finden Sie ein Beispiel, das ich erfunden habe, das Problem zu zeigen, das ich habe:

class Program
{
    public static void OutputDateTime(DateTime? datetime)
    {
        Console.WriteLine(datetime);
    }

    public static bool IsDateTimeHappy(DateTime datetime)
    {
        if (DateTime.Compare(datetime, DateTime.Parse("1/1")) == 0)
            return true;

        return false;
    }

    static void Main(string[] args)
    {
        DateTime myDateTime = DateTime.Now;
        OutputDateTime(IsDateTimeHappy(myDateTime) ? null : myDateTime);
        Console.ReadLine();                        ^
    }                                              |
}                                                  |
// This line has the compile issue  ---------------+

Auf der Linie oben angedeutet, ich den folgenden Compiler-Fehler erhalten:

Art des bedingten Ausdrucks kann nicht bestimmt werden, weil es keine implizite Konvertierung zwischen '' und 'System.DateTime'

Ich bin verwirrt, weil der Parameter ein Nullable Type ist (Datetime?). Warum braucht es überhaupt zu konvertieren? Wenn es null verwenden Sie dann das heißt, wenn es sich um ein Datum Zeit dann ist das verwenden.

Ich habe den Eindruck, dass:

condition ? first_expression : second_expression;

war das gleiche wie:

if (condition)
   first_expression;
else
   second_expression;

Dies ist eindeutig nicht der Fall. Was ist der Grund?

(ANMERKUNG:.? Ich weiß, dass wenn ich „MyDateTime“ eine Nullable-Datetime zu machen, dann wird es funktionieren, aber warum tut es es braucht

Wie ich bereits erwähnt dies ein konstruiertes Beispiel ist. In meinem realen Beispiel „MyDateTime“ ist ein Datenwert zugeordnet, die keine Nullwerte enthalten gemacht werden kann.)

War es hilfreich?

Lösung

Der Compiler schließt nicht den Typen des Ergebnisses des bedingten Operators aus der Nutzung des Ergebnisses, sondern von den Typen ihrer Argumente. Der Compiler schlägt fehl, wenn es diesen Ausdruck sieht, weil es nicht die Art des Ergebnisses ableiten kann:

IsDateTimeHappy(myDateTime) ? null : myDateTime;

Da null und DateTime nicht kompatibel sind, müssen Sie den Compiler sagen, was sollte der Typ sein. Ein Abguss sollte es tun:

DateTime? x = IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime;
OutputDateTime(x);

Nun wird der Compiler keine Probleme haben. Sie können auch die oben in einer Zeile schreiben, wenn Sie es vorziehen, (aber ich würde wahrscheinlich nicht tun):

OutputDateTime(IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime);

Eric Lippert hat eine gute Antwort dass auch hier relevant ist und weitere Einzelheiten über geht in, wie die Compiler bestimmt Typen.

Andere Tipps

Der Grund dafür ist der ternäre Operator erwartet, dass beide die Operanden vom gleichen Typ sein. Der ganze Operator get ausgearbeitet, bevor es zu einem Ergebnis (in diesem Fall in eine Funktion übergeben) zugeordnet ist, so dass der Compiler nicht wissen kann, was das Ergebnis Typ ist.

IsDateTimeHappy(myDateTime) ? null : myDateTime

Im obigen Fall gibt es keinen Conversion-Pfad zwischen null und DateTime. Sobald Sie einen von ihnen zu DateTime? werfen, kann der Compiler die andere umwandeln:

IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime
//OR
IsDateTimeHappy(myDateTime) ? null : (DateTime?)myDateTime

Die Faust Codezeile oben funktioniert, weil der Compiler kann DateTime zu DateTime? über eine implizite Konvertierung Operator konvertieren:

//In Nullable<T>
public static implicit operator T?(T value);

Die zweite Zeile funktioniert, weil null zu DateTime? zugeordnet werden kann, da diese ein Referenztyp ist.

Die implizite Konvertierung wird durch die return-Anweisung nicht erlaubt. Wenn Sie hatte

if (condition)
    return first_expression;
else
    return second_expression;

Dann würden Sie Äpfel mit Äpfeln zu vergleichen sein. Und Sie haben keine Probleme haben -. Wie Sie sagten

In Ihrem Fall sind Sie so viel Platz auf dem Stapel für ein DateTime- zugeordnet - was ein Nicht-Nullable-Wertetyp ist. So haben Sie eine Aussage machen, die keinen Sinn für den Compiler machen. Wenn Sie sagen, werde ich Ihnen eine A oder ein B passieren, dann die A und die B Notwendigkeit die gleiche Sache zu sein. In Ihrem Fall kann die B nie ein A sein.

Ich denke, das auch hier beantwortet wird: Nullable-Typen und der ternäre Operator: Warum ist `? 10: null` verboten

Ich hoffe, das ist es, was man braucht. =]

Was der Compiler sagt, ist:

  

Wenn IsDateTimeHappy(myDateTime) false ist, dann brauche ich einen Wert vom Typ DateTime zurückzukehren gleich zu myDateTime. Wenn es true ist, dann muss ich einen Wert zurückgeben gleich zu null, aber Sie haben mir nicht gesagt, welche Art soll es sein!

Deshalb Mark Antwort ist die Lösung. Nachdem Sie eine Besetzung zu sagen, die Compiler zur Verfügung stellen, welche Art von Wert zurückgegeben wird, wenn die Bedingung true ist, kann sie prüfen, ob die true und false Rückgabewerte umgerechnet werden können (oder sind) die gleiche Art.

Prost Mark! ; -)

Statt null Verwendung default(DateTime?) und dann beide Seiten des ternären werden kompatible Typen haben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top