Typ Ergebnis mit bedingtem Operator in C #
-
26-09-2019 - |
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 '
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.)
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 TypDateTime
zurückzukehren gleich zumyDateTime
. Wenn estrue
ist, dann muss ich einen Wert zurückgeben gleich zunull
, 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.