In VS2013 werden im folgenden Beispiel zwei verschiedene Fehler angegeben, wenn versucht wird, eine Funktion an den Konstruktor eines Worker zu übergeben. Dennoch sind Lambda-Funktionen mit demselben Prototyp in Ordnung.
Was mache ich falsch, und wie kann ich die Definition der Funktion GetA
ändern, damit sie übergeben wird?
Um Verwechslungen mit ähnlich klingenden Fragen zu vermeiden, die durch Missverständnisse über die Klassenvererbung verursacht werden, habe ich in diesem Beispiel absichtlich jede Vererbung vermieden.
WorkerA
kann nur einen Func<A>
im Contructor akzeptieren.
WorkerAorB
ist flexibler und kann entweder ein Func<A>
oder ein Func<B>
akzeptieren.
WorkerAandB
ist am fähigsten und kann gleichzeitig eine Func<A>
und eine Func<B>
akzeptieren (oder beides). Es ist meinem echten Code am nächsten.
Wenn jedoch Code im Manager versucht, Worker zu instanziieren, funktioniert WorkerA
wie erwartet, aber WorkerAorB
gibt den Fehler:
Fehler CS0121: Der Aufruf ist zwischen den folgenden Methoden oder nicht eindeutig Eigenschaften: 'WorkerAorB.WorkerAorB (System.Func & lt; A & gt;)' und 'WorkerAorB.WorkerAorB (System.Func & lt; B & gt;)'
WorkerAandB
gibt
Fehler CS0407: 'Ein ManagerA.GetA ()' hat den falschen Rückgabetyp
In jedem Fall scheint der Compiler nicht in der Lage zu sein zu bestimmen, welche Überladung verwendet werden soll, wenn ein Verweis auf eine reale Funktion und nicht auf eine Lambda-Variable oder eine vorhandene Variable Func<A>
und in den Fall WorkerAandB
übergeben wird Es wählt eindeutig die WRONG-Überladung aus und gibt einen Fehler über den Rückgabetyp der übergebenen Funktion aus.
Können die Funktionen GetA
oder GetAstatic
in irgendeiner Weise modifiziert werden, damit der Compiler die richtige Überladung erkennt oder nur lambdas und / oder explizit deklarierte Delegaten in diesem Kontext erlaubt sind?
Update: Einige Informationen, die ich im Beispiel weggelassen habe. In der Realität Problem, Klassen
%Vor%A
undB
sind in der Tat verwandt.Auch bei weiterer Reflexion des eigentlichen Problems ein Anruf nach
%Vor%wie
%Vor%war tatsächlich äquivalent zu
%Vor%Also für das eigentliche Problem habe ich das Äquivalent zum Löschen des zweiter Konstruktor im Beispielproblem, da sich herausstellt, dass die Überladung redundant ist.
In der Zwischenzeit habe ich die Antwort angenommen, die tatsächlich ein Potenzial hat Lösung für das Problem (obwohl eine offensichtliche, die ich nicht erwähnen wollte in der ursprünglichen Frage), obwohl es nicht war, was ich schließlich verwendete.
Die Antwort wäre das:
%Vor% Warum es ohne die Umwandlungen nicht funktioniert hat .... Scheint, dass für den Compiler GetA nicht vom Typ Func<A>
ist, sondern nur ein method group
Der Hauptteil von Eric Lipperts Antwort hier , wie es für diese Frage gilt, scheint die "Overhead-Auflösung" zu sein berücksichtigt Rückgabetypen nicht. " Wenn Sie also Ihr Beispiel umschreiben, indem Sie jedes Func
durch ein Action
ersetzen, verschwinden die Fehler, da es jetzt nicht leere Argumentlisten gibt, durch die die Mehrdeutigkeit aufgelöst wird.
Das allgemeine Problem ist, warum würden Sie Code so schreiben? Ich sehe die hypothetische Natur des Problems, aber es sollte niemals in der realen Welt existieren, weil wir Funktionen schreiben sollten, die tatsächlich wie erwartet lesen:
%Vor%Es gibt keine andere Möglichkeit, eine Funktion zum Abrufen einer Person nach ID zu schreiben, indem eine Funktion übergeben wird, die ein int zurückgibt.
Oder wenn Sie mehrere Konstruktoren erstellen, löst die Verwendung des korrekten objektorientierten Ansatzes ein Problem:
%Vor%Aber direkt zu Ihrer Frage ..
Können die GetA- oder GetAstatic-Funktionen in irgendeiner Weise modifiziert werden, um dem Compiler zu helfen, die richtige Überladung zu erkennen, oder sind in diesem Kontext nur Lambdas und / oder explizit deklarierte Delegaten erlaubt?
Soweit ich weiß, kann es nicht auf die Funktionsdefinitionen, aber es kann auf seine Verwendung gemacht werden:
%Vor%Tags und Links c# lambda overload-resolution member-functions