Bedingte Anweisung, unnötiger Cast des generischen Delegate

8

Ich habe dieses wirklich seltsame Problem mit einer bedingten Anweisung, wenn ich einen Action<T> Wert festlege. Es ist nicht so, dass ich nicht weiß, wie ich das umgehen soll, da es ziemlich einfach zu lösen ist, indem ein normales if verwendet wird.

Hier ist mein Problem:

%Vor%

Das gibt mir einen Compilerfehler mit der Nachricht

  

Es gibt keine implizite Konvertierung zwischen 'Methodengruppe' und 'Methodengruppe'.

Was seltsam ist, da ich nicht herausfinden kann, warum das illegal wäre.

Übrigens, die folgende Syntax macht dies gültig (aus Sicht des Compilers):

%Vor%

Vielleicht kannst du die Frage also lesen, warum ist die Besetzung notwendig?

    
thekip 16.08.2011, 14:04
quelle

4 Antworten

2

Sie fügen zwei ähnliche Konzepte zusammen:

A) Eine Methodengruppe. Eine Methodengruppe ist eine oder mehrere C # -Methoden mit demselben Namen. Es ist eine Abstraktion, die hauptsächlich vom Compiler verwendet wird; Sie können eine Methodengruppe nicht umgehen. Alles, was Sie mit einer Methodengruppe tun können, ist, sie aufzurufen oder einen Delegierten daraus zu erstellen. Sie können implizit einen Delegaten aus einer Methodengruppe erstellen, wenn die Typsignaturen übereinstimmen.

B) Ein Delegierter. Sie wissen, was ein Delegierter ist; Es hat eine spezifische Typ-Signatur und verweist direkt auf eine Methode. Sie können es nicht nur aufrufen, sondern auch weitergeben und als ein erstklassiges Objekt behandeln.

Im ersten Beispiel gibt Ihr Ausdruck eine Methodengruppe B auf der einen Seite und eine andere Methodengruppe C auf der anderen Seite zurück. Der ternäre Operator muss den gleichen Typ auf beiden Seiten zurückgeben, aber er weiß nicht, auf was er beide Seiten werfen soll. Der Variablentyp, dem das Ergebnis zugewiesen wurde ( Action<bool> ), bestimmt nicht den Typ des Ausdrucks. Es ist also mehrdeutig.

Im zweiten Beispiel legst du die Methodengruppe B an einen Action<bool> -Delegaten auf der einen Seite des ternären Operators. Bei dem Versuch, den Ausdruck zu disambiguieren, versucht der Compiler, jede Seite auf den Typ der anderen Seite zu werfen. Es kann die Methodengruppe C erfolgreich in eine Action<bool> umwandeln, also tut sie dies und der Ausdruck ist zulässig.

    
mquander 16.08.2011, 14:13
quelle
1

Weil B und C keine Delegierten sind. Sie sind Methodengruppen und können implizit in Delegaten konvertiert werden (insbesondere Action<bool> ), aber das ist nicht das Gleiche.

Der Typ des Bedingungsausdrucks muss in beiden Zweigen konsistent sein, und da B und C momentan Methodengruppen sind (die nicht typisiert sind), kann der Compiler nicht herausfinden, was der Typ sein soll. Wie Sie erfahren, gibt es keine implizite Konvertierung zwischen ihnen.

Ebenso kann nicht (oder zumindest nicht ) auf die andere Seite des Zuweisungsoperators schauen und sagen "Oh, es sollte sein Action<bool> ".

Wenn Sie einen Cast hinzufügen, wird der Typ des linken Verzweigungsausdrucks Action<bool> , und dort ist eine implizite Konvertierung zwischen der Methodengruppe auf der anderen Seite und dem Delegaten, also dem Compiler wieder glücklich: Der Typ des gesamten Ausdrucks ist Action<bool> .

    
dlev 16.08.2011 14:11
quelle
0

Ich denke, Eric wird mir wieder sagen, dass mein Begründung ist etwas falsch , aber ich werde es trotzdem versuchen und auf seine Korrektur hoffen :-)

Eine Methodengruppe, zum Beispiel B , hat keinen Typ, es ist kein Objekt ( B.GetType() wird nicht kompiliert).
Es kann leicht in einen Typ konvertiert werden, weshalb eine implizite Umwandlung existiert. Beispiel:

%Vor%

Wie Sie jedoch in der verknüpften Frage sehen können, versucht der ternäre Ausdruck einen Rückgabetyp zu finden, bei dem beide Teile des Ausdrucks übereinstimmen. Es weiß nicht, dass später eine Konvertierung in Action<bool> stattfinden soll. Da Methodengruppen keine Typen an sich sind, gibt es keine Konvertierung zwischen ihnen und B kann nicht in C konvertiert werden, und der Compiler beschwert sich gerade darüber.

Wenn Sie einen Teil des ternären Ausdrucks in Action<bool> umwandeln, teilen Sie dem Compiler mit, dass der Rückgabetyp dieser Typ sein soll, und überprüft, ob der andere Teil des ternären Ausdrucks eine implizite Umwandlung in diesen Typ unterstützt. Weil dies der Fall ist, wird der Code kompiliert.

    
Daniel Hilgarth 16.08.2011 14:12
quelle
-1

Eine Aktion ist eine bestimmte Delegatklasse, und es gibt keine implizite Konvertierung von / zu einem regulären Delegaten mit einer ähnlichen Signatur.

    
Dean Chalk 16.08.2011 14:10
quelle