Gut zu sehen, wie ich in einer Rolle für das Austeilen von Text heute Abend bin, werde ich meinen eigenen Stab darin haben. Ich sollte beachten, dass ich kein Experte für den C# -Compiler bin, ich habe die Spezifikation (keine von ihnen ... für irgendetwas) gelesen, und obwohl dieser Artikel, den Sie verlinkt haben, wirklich interessant war, würde ich lügen, wenn ich es sagen würde war eine Art von Experte auf dem entweder (oder auch alles zu 100% verstanden).
Caveats beiseite lässt, ist mein nehmen auf Ihre Frage so:
Gibt es eine Möglichkeit, die ich hier die Typdefinitionen verallgemeinern?
Ich denke, die kurze Antwort ist nein. Mit den bereitgestellten Informationen gibt es einfach nicht genug Informationen für den Typinferenzteil des C# -Compilers, um genug Informationen aus der Verwendung der verschiedenen Variablen abzuleiten.
Wie die anderen Antworten hier zeigen, kann es vereinfacht werden. Sie können @ Lees IdentityFunc
verwenden, um Typrückschluss mit var identity
zuzulassen. Aber auch mit diesem Zusatz ist es immer noch nicht möglich, mit Ihrem Beispielcode auf alle Typvariablen von Compose
zu schließen.
Stellen Sie sich folgende Situation:
public static Func<T, V> Compose<T, U, V>(this Func<U, V> f, Func<T, U> g)
{
return x => f(g(x));
}
public static T Identity<T> (this T value)
{
return value;
}
public static Func<T, T> IdentityFunc<T>(this T value)
{
return (Func<T, T>)Identity;
}
und
public static void Run()
{
var a = 3; // a is int
var i = a.IdentityFunc(); // i is Func<int, int>;
var test = i.Compose(n => n)(a) // test is expected to be int
}
Zunächst dies erscheinen mag, als ob test
leicht zu int
rein zufällig. Der Rückgabetyp i.Compose
kann jedoch erst nachträglich aus seiner Verwendung abgeleitet werden. Der C# -Compiler wird dies offensichtlich nicht erlauben.
public static void Run()
{
var a = 3; // a is int
var i = a.IdentityFunc(); // i is Func<int, int>;
var c = i.Compose(n => n) // c is Func<T, int> - T cannot be resolved without knowledge of n
var test = c(a); // ideally have type inference infer c (Func<T, int>) as Func<int, int>
}
In diesem Beispiel bei Verwendung von c
mit a
würde der Compiler nachträglich den Rückgabetyp des Anrufs i.Compose<T, U, V>(n => n)
schließen muß Func<int, int>
sein. Dies ist im C# -Compiler offensichtlich nicht möglich. Nehmen Sie den Anruf c(a)
und der Compiler würde keine Kenntnis von der Verwendung von c
, die jede Möglichkeit der Ableitung von T
(nicht, dass es sowieso kann) zu entfernen. Es ist möglich, dass ein fortgeschritteneres Typ-Inferenzsystem diese Art von Schlussfolgerung basierend auf der Verwendung einer generischen Rückkehr durchführen könnte (möglicherweise F # - ein anderes Thema, zu dem ich kein Experte bin).
Da Wes Dyer keine spezifische Verwendung dieses bestimmten Beispiels bietet, ist es unbekannt, ob es eine andere Magie gibt, die er verwendet, um den Grad der Typinferenz zu berücksichtigen, die Sie erreichen möchten.
Mehr qualifizierte Menschen wie Eric Lippert würden in der Lage sein, Sie mit einem viel höheren Detaillierungsgrad (und technische Genauigkeit/Schärfe) zu bieten. Ich habe eine große Antwort gelesen, die er hier auf eine Frage über Typinferenz geschrieben hat, aber ich kann sie nicht finden. Sein blog hat viele gute Informationen. Sie könnten versuchen, ihn zu kontaktieren, wenn Sie interessiert sind. Auch seine Antwort auf diese Frage hier diskutiert Monaden (und verlinkt schließlich zurück zu Wes Dyer's Artikel) kaufen Sie könnten daran interessiert sein, es zu lesen: Monad in plain English? (For the OOP programmer with no FP background)
Können Sie genauere Informationen über das, was Sie erreichen wollen? Derzeit ist Ihre Compose-Funktion zu eingeschränkt, um eine Typrückschluss von T von einem Lambda zu ermöglichen. Es kann einfach nicht genug Informationen von der Verwendung erhalten. – jeffora
aktualisierte die Frage. – CaptainCasey