Warum wird dies nicht kompiliert?
int? number = true ? 5 : null;
Der Typ des bedingten Ausdrucks kann nicht bestimmt werden, da keine implizite Konvertierung zwischen 'int' und <null> erfolgt
Warum wird dies nicht kompiliert?
int? number = true ? 5 : null;
Der Typ des bedingten Ausdrucks kann nicht bestimmt werden, da keine implizite Konvertierung zwischen 'int' und <null> erfolgt
Antworten:
Die Spezifikation (§7.14) besagt, dass es für den bedingten Ausdruck b ? x : ydrei Möglichkeiten gibt, entweder xund ybeide haben einen Typ und bestimmte gute Bedingungen sind erfüllt, nur eine von xund yhat einen Typ und bestimmte gute Bedingungen sind erfüllt, oder ein Fehler bei der Kompilierung tritt ein. Hier bedeutet "bestimmte gute Bedingungen", dass bestimmte Konvertierungen möglich sind, auf die wir im Folgenden näher eingehen werden.
Wenden wir uns nun dem deutschen Teil der Spezifikation zu:
Wenn nur einer von
xundyeinen Typ hat und beidexundyimplizit in diesen Typ konvertierbar sind, dann ist dies der Typ des bedingten Ausdrucks.
Das Problem hier ist, dass in
int? number = true ? 5 : null;
Nur eines der bedingten Ergebnisse hat einen Typ. Hier xist eine intwörtliche, und yist nulldie sich nicht einen Typ haben und nullist nicht implizit konvertierbar zu einem int1 . Daher werden "bestimmte gute Bedingungen" nicht erfüllt, und es tritt ein Fehler bei der Kompilierung auf.
Es gibt zwei Möglichkeiten, dies zu umgehen:
int? number = true ? (int?)5 : null;
Hier sind wir noch in dem Fall, dass nur einer von xund yeinen Typ hat. Beachten Sie, dassnull nach wie vor nicht über eine Art noch der Compiler habe kein Problem mit diesem , weil (int?)5und nullbeide implizit konvertierbar int?(§ 6.1.4 und §6.1.5).
Der andere Weg ist offensichtlich:
int? number = true ? 5 : (int?)null;
aber jetzt müssen wir a lesen andere Klausel in der Spezifikation zu verstehen, warum dies in Ordnung ist:
Wenn
xhat TypXundyhat TypYdann
Wenn eine implizite Konvertierung (§6.1) von
XbisY, aber nicht vonYbis bestehtX,Yist dies der Typ des bedingten Ausdrucks.Wenn eine implizite Konvertierung (§6.1) von
YbisX, aber nicht vonXbis bestehtY,Xist dies der Typ des bedingten Ausdrucks.Andernfalls kann kein Ausdruckstyp ermittelt werden, und es tritt ein Fehler bei der Kompilierung auf.
Hier xist vom Typ intund yist vom Typ int?. Es gibt keine implizite Konvertierung von int?nach int, aber es gibt eine implizite Konvertierung von intnach, int?so dass der Typ des Ausdrucks ist int?.
1 : Beachten Sie ferner, dass der Typ der linken Seite bei der Bestimmung des Typs des bedingten Ausdrucks ignoriert wird, was hier häufig zu Verwirrung führt.
new int?()anstelle von (int?)null.
DateTime, wenn dies erforderlich ist(DateTime?)
null hat keinen identifizierbaren Typ - es muss nur ein wenig gestoßen werden, um glücklich zu werden:
int? number = true ? 5 : (int?)null;
int? number = true ? 5 : null as int?;
int? number = true ? 5 : (int?)null;und int? number = true ? (int?)5 : null;beide kompilieren !! Scratch, Scratch
Wie andere bereits erwähnt haben, ist die 5 eine intund nullkann nicht implizit in konvertiert werdenint .
Hier sind andere Möglichkeiten, um das Problem zu umgehen:
int? num = true ? 5 : default(int?);
int? num = true ? 5 : new int?();
int? num = true ? 5 : null as int?;
int? num = true ? 5 : (int?)null;
int? num = true ? (int?)5 : null;
int? num = true ? 5 as int? : null;
int? num = true ? new int?(5) : null;
Auch überall, wo Sie sehen int?, können Sie auch verwenden Nullable<int>.
In C# 9diesem Blog ist jetzt erlaubt
Ziel getippt? und ?
Manchmal bedingt ?? und ?: Ausdrücke haben keinen offensichtlichen gemeinsamen Typ zwischen den Zweigen. Solche Fälle schlagen heute fehl, aber C # 9.0 lässt sie zu, wenn es einen Zieltyp gibt, in den beide Zweige konvertieren:
Person person = student ?? customer; // Shared base type
int? result = b ? 0 : null; // nullable value type
Oder dein Beispiel:
// Allowed in C# 9.
int? number = true ? 5 : null;