2015-01-07 2 views
13

ich habe folgende ASP.NET-Api 2 Aktion mit einem ternären, wenn Rückkehr:„Kann nicht bestimmt werden, weil es keine implizite Konvertierung ist“ mit ternery wenn Rückkehr

[HttpDelete] 
public IHttpActionResult Delete() 
{ 
    bool deleted; 

    // ... 

    return deleted ? this.Ok() : this.NotFound(); 
} 

ich

erhalten

Art des bedingten Ausdrucks kann nicht bestimmt werden, da keine implizite Konvertierung zwischen ‚System.Web.Http.Results.OkResult‘ ist und ‚System.Web.Http.Results.NotFoundResult‘

, wenn beide IHttpActionResult implementieren.

Allerdings, wenn ich die ternären entfernen, wenn der Compiler ist glücklich:

if (deleted) 
{ 
    return this.Ok(); 
} 
return this.NotFound(); 

Warum ist das?

Antwort

14

Sie müssen explizit das Ergebnis IHttpActionResult würfe

return deleted ? (IHttpActionResult) this.Ok() : this.NotFound(); 

Edit:

Was Frage Grants:

Warum Sams zweiten Codeblock Arbeit, ohne explizit Casting zu IHttpActionResult, nur aus Neugier? Ist das etwas Besonderes zu dem bedingten Operator?:?

Lassen Sie uns eine einfache Demonstration erstellen. Angenommen, den folgenden Code:

public interface IFoo { } 

public class B : IFoo { } 

public class C : IFoo { } 

Und dann folgendes:

public class A 
{ 
    IFoo F(bool b) 
    { 
     return b ? (IFoo) new B() : new C(); 
    } 
} 

Mal sehen, wie der Compiler de-kompiliert den ternären Operator:

private IFoo F(bool b) 
{ 
    IFoo arg_13_0; 
    if (!b) 
    { 
     IFoo foo = new C(); 
     arg_13_0 = foo; 
    } 
    else 
    { 
     arg_13_0 = new B(); 
    } 
    return arg_13_0; 
} 

Die explizite Umwandlung genügt der Compiler, um zu folgern, dass die Variable vom Typ IFoo sein sollte und somit unser gesamtes if-else erfüllt. Deshalb ist es genug für uns, den Compiler nur einmal von unserem Typ-Cast zu "deuten".

@dcastro hat den genauen Teil der Sprachspezifikation referenziert, der die Steuerung des Typs bestimmt, siehe für die Textbuchdefinition.

+2

Warum Sams zweiten Codeblock Arbeit ohne zu 'IHttpActionResult' ausdrücklich zu Gießen, gerade aus Neugierde? Ist das etwas Besonderes für den bedingten '?:' Operator? –

+0

@GrantWinney Ja, es ist – dcastro

+0

@GrantWinney Siehe meine bearbeitete Antwort. –

6

in einem ternären Ausdruck A? B : C, muss es ein Referenzumsetzungs sein (beispielsweise von einem Basistyp zu einem abgeleiteten Typ oder umgekehrt) entweder von B auf C oder C zu B.

Sie erwartet der Compiler, um den am meisten abgeleiteten gemeinsamen Vorfahren der beiden Typen zu finden (was IHttpActionResult ist) - der Compiler macht das nicht.

Als allgemeine Faustregel gilt, dass der Typ des Ergebnisses eines Ausdrucks im Ausdruck selbst enthalten sein muss. I.e.bool? dog : cat kann keine animal zurückgeben, da keine Variable vom Typ animal Teil des Ausdrucks ist.

Aus dem C# Language Specification Abschnitt 7.14 Bedingte Betreiber:

Die zweite und dritte Operanden, x und y, der Operator?: Kontrolle der Typ des bedingten Ausdrucks.

  • Wenn x hat X-Typen und Y-Typen hat Y dann
    • Wenn eine implizite Konvertierung (§6.1) von X nach Y vorhanden ist, aber nicht von Y zu X, dann ist Y der Typ der bedingten Ausdruck
    • Wenn eine implizite Konvertierung (§6.1) von Y nach X, aber nicht von X nach Y existiert, dann ist X der Typ des bedingten Ausdrucks .
    • Ansonsten kann kein Ausdruck Typ bestimmt werden, und ein Fehler bei der Kompilierung auftritt
Verwandte Themen