2008-10-20 11 views
29

Ich bin neugierig, warum eine implizite Umwandlung nicht in ...In C# warum nicht auch ein bedingter Operator werfen implizit auf eine Nullable Type

int? someValue = SomeCondition ? ResultOfSomeCalc() : null; 

und warum ich eine explizite Umwandlung statt

zu erfüllen haben

Es scheint mir, dass der Compiler alle notwendigen Informationen hat, um eine implizite Casting-Entscheidung zu treffen, nein?

+5

Ich werde Ihren Titel nicht selbst bearbeiten, aber ich schlage vor, Sie ändern das Wort terrnarary zu bedingten - der Operator heißt der bedingte Operator. Es ist * ein * ternärer Operator - und momentan der einzige -, der aber nichts anderes als die Anzahl der Operanden beschreibt. –

+3

Vielleicht bin ich frecher, aber ich werde ... –

+0

@MarcGravell Ich bin frech und hoffentlich korrekt - sollte nicht der Titel '** der ** bedingte Operator' dann sein? :) –

Antwort

27

Der relevante Abschnitt der Spezifikation ist 3,0 C# 7.13, der bedingte Operator:

Die zweiten und dritten Operanden des: Bedienen der Typ des bedingten Ausdrucks. Seien X und Y die Typen des zweiten und dritten Operanden. Dann,

Wenn X und Y sind der gleiche Typ, dann ist dies der Typ der bedingten Andernfalls, wenn eine implizite Umwandlung (§6.1) existiert von X nach Y, aber nicht von Y nach X, dann ist Y der Typ des bedingten Ausdrucks Andernfalls, wenn eine implizite Konvertierung (§ 6.1) von Y nach X existiert, aber nicht von X nach Y, dann ist X der Typ des Bedingungsausdrucks. Andernfalls kann kein Ausdruckstyp ermittelt werden, und ein Fehler bei der Kompilierung tritt auf.

+6

Zusammenfassend berücksichtigt es nicht, welchen Typ Sie zuweisen in das Ergebnis der Operation. Es versucht lediglich, die richtige Seite des Gleichheitstyps herauszufinden - mit Unkenntnis der nullbaren Typen. – TheSoftwareJedi

+0

Aber betrachten wir den Fall der ternären Verkettung. Wie sonst würde es wissen? –

+0

@DJ Floetic: es würde am "innersten" beginnen?: Operator, herauszufinden, welche Art von diesem Ergebnis, dann arbeiten Sie sich aus. –

14

Ich bin auch genervt, dass es den Typ basierend auf der Zuordnung nicht ableiten kann, vor allem, wenn es ein Werttyp ist. Es gibt jedoch Gründe, wenn Sie in Objekt-Hierarchien kommen.

Wenn "ResultOfSomeCalc()" ein "int?" Zurückgibt, dann würde dies funktionieren. C# muss den Typ herausfinden, unabhängig davon, was sich links von der Zuweisung befindet. Sie sagen also, dass Sie eine Null oder ein int zurückgeben werden - und die Logik im Compiler existiert nicht, um eine Nullable als gemeinsamen Nenner zu ersetzen.

Beachten Sie, dass diese Varianten Arbeit tun, und es kann Ihnen helfen, zu verstehen:

object someValue = true ? new Nullable<int>(ResultOfSomeCalc()) : null; 

object someValue = true ? (int?)ResultOfSomeCalc() : null; 

Hoffnung, das hilft.

+0

Auch eine sehr gute Antwort, ich akzeptierte DJ's und updoted deins. –

0

auch Wenn Ihre Funktion ResultofSomeCalc() int zurückgibt? dann wird das funktionieren.

Wenn Ihre Funktion int zurückgibt, dann gibt der Compiler die Warnung: Art des bedingten Ausdrucks nicht bestimmt werden kann, weil es keine implizite Konvertierung ist, dass zwischen ‚int‘ und ‚‘
Ich vermute, ist, was Sie sehen . Beide Ausdrücke im Bedingungsoperator "?:" Müssen den gleichen Typ haben oder über einen impliziten Cast in denselben Typ konvertierbar sein.

Ändern Sie den Rückgabetyp von ResultOfSomeCalc in int?, Oder Sie müssen die Umwandlung in den Nullausdruck haben.

5

Es scheint, als wäre dies etwas, was der Compiler für sich selbst herausfinden sollte, aber es gibt eine andere Möglichkeit, dies zu tun, mit dem Standard-Schlüsselwort. Es könnte das kleinste bisschen weniger hässlich als die Besetzung sein:

int? someValue = SomeCondition ? ResultofSomeCalc() : default(int?); 

Diese Verwendung von Standard scheint nicht gut dokumentiert werden, ist aber funktioniert.Zumindest hält es Sie davon ab, Ihren Code mit magischen Werten zu bestreuen (ich behaupte, dass null/zero/false/etc in der Tat magische Werte sind).

0

Machen Sie Ihre Funktion ResultOfSomeCalc() 's Rückgabetyp wie Nullmarke Int wie (int?)
int? someValue = (int?) SomeCondition? ResultofSomeCalc(): (int?) Null;

Verwandte Themen