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 : y
drei Möglichkeiten gibt, entweder x
und y
beide haben einen Typ und bestimmte gute Bedingungen sind erfüllt, nur eine von x
und y
hat 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
x
undy
einen Typ hat und beidex
undy
implizit 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 x
ist eine int
wörtliche, und y
ist null
die sich nicht einen Typ haben und null
ist nicht implizit konvertierbar zu einem int
1 . 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 x
und y
einen Typ hat. Beachten Sie, dassnull
nach wie vor nicht über eine Art noch der Compiler habe kein Problem mit diesem , weil (int?)5
und null
beide 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
x
hat TypX
undy
hat TypY
dann
Wenn eine implizite Konvertierung (§6.1) von
X
bisY
, aber nicht vonY
bis bestehtX
,Y
ist dies der Typ des bedingten Ausdrucks.Wenn eine implizite Konvertierung (§6.1) von
Y
bisX
, aber nicht vonX
bis bestehtY
,X
ist dies der Typ des bedingten Ausdrucks.Andernfalls kann kein Ausdruckstyp ermittelt werden, und es tritt ein Fehler bei der Kompilierung auf.
Hier x
ist vom Typ int
und y
ist vom Typ int?
. Es gibt keine implizite Konvertierung von int?
nach int
, aber es gibt eine implizite Konvertierung von int
nach, 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 int
und null
kann 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# 9
diesem 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;