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, anstelle Predicate
oder Action
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?
var x1 = (ref int y)=>123;
Es gibt keinen Func<T>
Typ, der eine Referenz benötigt.
var x2 = y=>123;
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?)
var x3 = (int y)=>null;
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.
var x4 = (int y)=>{ throw new Exception(); }
Auch hier kennen wir den Rückgabetyp nicht und diesmal kann er ungültig sein.
var x5 = (int y)=> q += y;
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:
var xAnon = (int y)=>new { Y = y };
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:
Func<A, R> WorkItOut<A, R>(Func<A, R> f) { return f; }
...
var xAnon = WorkItOut((int y)=>new { Y = y });
und jetzt ermittelt die Inferenz des Methodentyps, was der Funktionstyp ist.
Func<>
akzeptiert bis zu 16 Argumente.