Ich habe folgenden Code:
Func<string, bool> comparer = delegate(string value) {
return value != "0";
};
Folgendes wird jedoch nicht kompiliert:
var comparer = delegate(string value) {
return value != "0";
};
Warum kann der Compiler nicht herausfinden, dass es sich um eine handelt Func<string, bool>
? Es benötigt einen String-Parameter und gibt einen Booleschen Wert zurück. Stattdessen gibt es mir den Fehler:
Einer implizit typisierten lokalen Variablen kann keine anonyme Methode zugewiesen werden.
Ich habe eine Vermutung und das heißt, wenn die var-Version kompiliert würde , würde es an Konsistenz mangeln , wenn ich Folgendes hätte:
var comparer = delegate(string arg1, string arg2, string arg3, string arg4, string arg5) {
return false;
};
Das Obige wäre nicht sinnvoll, da Func <> nur bis zu 4 Argumente zulässt (in .NET 3.5, das verwende ich). Vielleicht könnte jemand das Problem klären. Vielen Dank.
Func<>
akzeptiert bis zu 16 Argumente.Func<string, bool>
? Es sieht aus wie einConverter<string, bool>
für mich!Dim comparer = Function(value$) value <> "0"
Antworten:
Andere haben bereits darauf hingewiesen , dass es unendlich viele mögliche Delegattypen , dass Sie könnte gemeint haben; Was ist das Besondere daran,
Func
dass es verdient, anstellePredicate
oderAction
oder einer anderen Möglichkeit die Standardeinstellung zu sein ? Und warum ist es für Lambdas offensichtlich, dass die Absicht besteht, die Delegatenform anstelle der Ausdrucksbaumform zu wählen?Aber wir könnten sagen, dass dies etwas
Func
Besonderes ist und dass der abgeleitete Typ eines Lambda oder einer anonymen Methode Func von etwas ist. Wir hätten immer noch alle möglichen Probleme. Welche Typen möchten Sie für die folgenden Fälle ableiten?Es gibt keinen
Func<T>
Typ, der eine Referenz benötigt.Wir kennen den Typ des formalen Parameters nicht, obwohl wir die Rückgabe kennen. (Oder tun wir das? Ist die Rückgabe int? Long? Short? Byte?)
Wir kennen den Rückgabetyp nicht, aber er kann nicht ungültig sein. Der Rückgabetyp kann ein beliebiger Referenztyp oder ein nullbarer Werttyp sein.
Auch hier kennen wir den Rückgabetyp nicht und diesmal kann er ungültig sein.
Soll das eine nicht rückgebende Anweisung Lambda sein oder etwas, das den Wert zurückgibt, der q zugewiesen wurde? Beide sind legal; welches sollen wir wählen?
Nun, Sie könnten sagen, unterstützen Sie einfach keine dieser Funktionen. Unterstützen Sie einfach "normale" Fälle, in denen die Typen ausgearbeitet werden können. Das hilft nicht. Wie erleichtert mir das das Leben? Wenn die Funktion manchmal funktioniert und manchmal fehlschlägt, muss ich immer noch den Code schreiben, um all diese Fehlersituationen zu erkennen und für jede eine aussagekräftige Fehlermeldung zu geben. Wir müssen immer noch all dieses Verhalten spezifizieren, es dokumentieren, Tests dafür schreiben und so weiter. Dies ist eine sehr teure Funktion , die dem Benutzer ein halbes Dutzend Tastenanschläge erspart. Wir haben bessere Möglichkeiten, der Sprache einen Mehrwert zu verleihen, als viel Zeit damit zu verbringen, Testfälle für eine Funktion zu schreiben, die die Hälfte der Zeit nicht funktioniert und in Fällen, in denen sie funktioniert, kaum Vorteile bringt.
Die Situation, in der es tatsächlich nützlich ist, ist:
weil es für dieses Ding keinen "sprechbaren" Typ gibt. Wir haben dieses Problem jedoch ständig und verwenden nur die Inferenz des Methodentyps, um den Typ abzuleiten:
und jetzt ermittelt die Inferenz des Methodentyps, was der Funktionstyp ist.
quelle
Nur Eric Lippert weiß es genau, aber ich denke, das liegt daran, dass die Signatur des Delegatentyps den Typ nicht eindeutig bestimmt.
Betrachten Sie Ihr Beispiel:
Hier sind zwei mögliche Schlussfolgerungen für das, was
var
sein sollte:Welches sollte der Compiler ableiten? Es gibt keinen guten Grund, sich für den einen oder anderen zu entscheiden. Und obwohl a
Predicate<T>
funktional äquivalent zu a istFunc<T, bool>
, handelt es sich auf der Ebene des .NET-Typsystems immer noch um unterschiedliche Typen. Der Compiler kann daher den Delegatentyp nicht eindeutig auflösen und muss die Typinferenz nicht bestehen.quelle
Eric Lippert hat einen alten Beitrag darüber, wo er sagt
quelle
Unterschiedliche Delegierte werden als unterschiedliche Typen betrachtet. z. B.
Action
ist anders alsMethodInvoker
und eine Instanz vonAction
kann keiner Variablen vom Typ zugewiesen werdenMethodInvoker
.Also, wenn man einen anonymen Delegierten (oder Lambda) mag
() => {}
, ist es einAction
oder einMethodInvoker
? Der Compiler kann es nicht sagen.Wenn ich einen Delegatentyp deklariere, der ein
string
Argument nimmt und einen zurückgibtbool
, wie würde der Compiler dann wissen, dass Sie wirklich einenFunc<string, bool>
anstelle meines Delegatentyps wollten ? Der Delegatentyp kann nicht abgeleitet werden.quelle
Die folgenden Punkte stammen aus dem MSDN in Bezug auf implizit typisierte lokale Variablen:
MSDN-Referenz: Implizit typisierte lokale Variablen
Berücksichtigen Sie Folgendes in Bezug auf anonyme Methoden:
MSDN-Referenz: Anonyme Methoden
Ich würde vermuten, dass der Compiler nicht richtig ableiten kann, welcher Typ am besten zuzuweisen ist, da die anonyme Methode tatsächlich unterschiedliche Methodensignaturen hat.
quelle
Mein Beitrag beantwortet nicht die eigentliche Frage, aber die zugrunde liegende Frage:
"Wie vermeide ich es, einen flüchtigen Typ wie tippen zu müssen
Func<string, string, int, CustomInputType, bool, ReturnType>
?" [1]Als fauler / hackiger Programmierer, der ich bin, habe ich mit der Verwendung experimentiert
Func<dynamic, object>
- die einen einzelnen Eingabeparameter verwendet und ein Objekt zurückgibt.Für mehrere Argumente können Sie es folgendermaßen verwenden:
Tipp: Sie können verwenden,
Action<dynamic>
wenn Sie kein Objekt zurückgeben müssen.Ja, ich weiß, dass es wahrscheinlich gegen Ihre Programmierprinzipien verstößt, aber das macht für mich und wahrscheinlich einige Python-Codierer Sinn.
Ich bin ziemlich unerfahren bei Delegierten ... wollte nur mitteilen, was ich gelernt habe.
[1] Dies setzt voraus, dass Sie keine Methode aufrufen, für die ein vordefinierter
Func
Parameter erforderlich ist. In diesem Fall müssen Sie diese flüchtige Zeichenfolge eingeben: /quelle
Wie ist das?
quelle