2017-10-04 5 views
-1

Ich habe dieses Stück CodeWarum fragt der Operator?: Nach einer expliziten Besetzung?

 StateMachine.State = string.IsNullOrEmpty(MyString) ? 
      (IState) StateMachine.StateA : StateMachine.StateB; 

ich es auch schreiben kann als

 if (string.IsNullOrEmpty(MyString)) 
      StateMachine.State = StateMachine.StateA; 
     else 
      StateMachine.State = StateMachine.StateB; 

State vom Typ IState und StateA und StateB beide IState implementieren.

Im ersten Snippet verlangt der Compiler eine explizite Umwandlung, während er in der zweiten nicht benötigt wird. Warum wird es im ersten Beispiel benötigt?

EDIT: Die vorgeschlagene doppelte Frage deckt meine Frage nicht vollständig ab. Meine Frage betrifft Objekte und Interfaces, während die andere Frage primitive Datentypen und konstante Zahlen betrifft. Besonders der Vorschlag von Quetzalcoatl über die Deklarationen ist sehr wertvoll.

Das Lesen der Antwort auf die vorgeschlagene doppelte Frage hätte mich niemals in diese Richtung weisen können.

Antwort

3

Dies geschieht, wenn in Ausdruck x ? a : b die A und B verschiedenen Typen zurückgeben.

Werfen Sie einen Blick auf:

double a = 5; 
decimal b = 4; 
var z = x ? a : b; 

was die Art von Z sein sollte? Selbst wenn A und B von einem kompatiblen Typ wären, sagen wir int und long, wie sollte der Compiler raten, was er zurückgeben soll? sollte das Ergebnis int oder lang sein?

In Ihrem Fall ist StateA wahrscheinlich vom Typ "classA" und StateB vom Typ "classB". Beide Klassen implementieren IState, so funktioniert eine einfache Zuordnung, aber wenn Sie es in ?: Operator setzen, kann der Compiler nicht entscheiden, ob das Ergebnis ?: Operator classA oder classB sein soll.

Und ja, ich irre mich nicht: der Compiler denkt nicht einmal an ISate. Warum? Da Klasse A und Klasse B möglicherweise viele andere allgemeine Schnittstellen oder Basistypen haben. Sie können beide implementieren IState oder IEnumerable, oder .. object bei extrem. Welche gemeinsame Basisklasse sollte der Compiler auswählen? Es ist schwer zu entscheiden, also versucht es nicht zu erraten.

Es gibt eine sehr einfache Lösung, außer dem expliziten Casting, das Sie bereits selbst entdeckt haben. Ändern Sie einfach den Rückgabetyp der StateA- und StateB-Felder/-Eigenschaften.

Gerade jetzt, haben Sie wahrscheinlich:

class StateMachine 
{ 
    public ClassA StateA {get .. } 
    public ClassB StateB {get .. } 
} 

da beide IState implementieren, nur das ändern:

class StateMachine 
{ 
    public IState StateA {get .. } 
    public IState StateB {get .. } 
} 

letzteren Weg Ferner (die staatliche Instanz nur durch die Schnittstelle bereitstellt), Dies ist wahrscheinlich noch wünschenswerter, da, wenn StateMachine-Eigenschaften als ein "Repository von Zuständen" ausgewählt werden sollen, die Codestelle, die diese Zustände auswählt, wahrscheinlich nicht die genauen Implementierungstypen dieser Zustände kennen sollte - aber natürlich das ist nicht notwendig und hängt von Ihrem Design ab.

+0

Das war's! Ein sehr guter Vorschlag, meine Erklärungen von StateA und StateB zu IStates zu ändern. Vielen Dank! – ffonz

Verwandte Themen