2015-07-17 5 views
6

Ich arbeite an einer Windows Forms-Anwendung, und es enthält benutzerdefinierte Steuerelemente mit Methoden, die potenziell von anderen Threads als dem UI-Thread aufgerufen werden können. So also diese Methoden ein wenig aussehen wie diese Ausnahmen zu verhindern:Konvertieren Sie implizit Methodengruppe in Delegat (für Argument von Control.Invoke)

public void DoSomeStuff() 
{ 
    if (InvokeRequired) 
    { 
     Invoke((Action)DoSomeStuff); 
    } 
    else 
    { 
     // Actually do some stuff. 
    } 
} 

Die explizite Umwandlung der Methodengruppe DoSomeStuff zu einem Action meine Aufmerksamkeit erregt, und so habe ich gesucht, in Delegierte und andere verwandte Themen tiefer als ich vorher habe.

Obwohl ich einige Fragen hier gesehen habe, habe ich nicht in der Lage gewesen, genau die Antwort auf meinen finden, das ist:

Warum wird die Methodengruppe DoSomeStuff explizite Umwandlung erfordert ein Action in diesem Fall?

Wenn ich die Besetzung zu entfernen, dann bekomme ich zwei Fehler:

Fehler 102 Argument 1: kann nicht von 'Methodengruppe' zu

'System.Delegate' konvertieren

Error 101 Die besten überladene Methode Übereinstimmung für 'System.Windows.Forms.Control.Invoke (System.Delegate, params Objekt [])' hat einige ungültige Argumente

The Tatsache, dass der Compiler anscheinend verwirrt ist, welche Überladung von Invoke zu verwenden scheint wie ein ziemlich großer Hinweis, aber ich bin mir immer noch nicht sicher, warum genau das nicht herausfinden kann. Ich würde erwarten, dass der Compiler daraus folgert, dass die erste Überladung von Invoke, die ein einzelnes Delegate-Argument benötigt, diejenige ist, die verwendet werden sollte.

Ich würde erwarten, dass, weil es kein Problem, wenn der Code wie folgt geschrieben:

Action a = DoSomeStuff; 
Invoke(a); 

Die Methodengruppe DoSomeStuff kann implizit in den Action Delegattyp umgewandelt werden, und Action herleitet (technisch?) Aus System.Delegate, also Invoke kann das Argument a ohne Probleme behandeln. Aber warum kann die implizite Konvertierung nicht vom Compiler ausgeführt werden, wenn ich versuche, DoSomeStuff als Argument direkt zu übergeben? Um ehrlich zu sein, bin ich nicht von meiner eigenen Logik überzeugt, aber ich bin mir immer noch nicht sicher, was ich vermisse.

Antwort

2

Das Problem ist nicht, dass der Compiler Probleme bei der Auswahl einer Überladung hat. Die Überbelichtung "beste Übereinstimmung" ist die, die Sie wollen, aber sie hat ungültige Argumente. Die C# -Sprache definiert keine implizite Konvertierung von der Methodengruppe (DoSomeStuff) zu System.Delegate.

Sie könnten sagen, dass der Compiler nur einen der Action/Func Typen auswählen sollte und dies wurde als Sprachfeature angefordert. Im Moment ist dies nicht Teil von C#. (Ich weiß nicht warum; ich hoffe, dass die Sprachanfrage durchgeht.)

System.Windows.Forms.Control.Invoke wurde in .NET 1.0 erstellt. Heute würde man folgende Signaturen verwenden:

void Invoke(Action action); 
Task InvokeAsync(Action action); 

Und es würde einfach funktionieren.

Versuchen Sie, die Migration zu await zu machen, und das hört auf, ein Problem zu sein.

+0

> Sie könnten sagen, dass der Compiler nur einen der Action/Func-Typen auswählen sollte und dies als Sprachfeature angefordert wurde Dies zerfällt sehr leicht: 'void Foo (out string abc);' Ist nicht darstellbar mit 'Action' oder' Func'. Wenn sie Action/Func-Inferenz als Sprachfeature implementieren, wäre diese Funktion kaputt. – GeirGrusom

+0

@GeirGrusom Mit dieser speziellen Signatur könnte die Konvertierung fehlschlagen (statisch). Es ist ein seltener Fall, ich denke, es ist in Ordnung, hier einen Fehler zu zeigen. Nicht jede Methode kann als Action/Func dargestellt werden, aber 99% davon können in der Praxis sein. Alle Delegattypen sollten strukturell mit impliziten Konvertierungen behandelt werden, wenn dies sinnvoll ist. – usr

+0

Ich glaube nicht, dass es in Ordnung ist. Der Fehler wird angezeigt, da das Feature grundlegend beschädigt ist. – GeirGrusom

Verwandte Themen