C#泛型方法类型参数推理

C#泛型方法类型参数推理,c#,type-inference,C#,Type Inference,有什么方法可以概括这里的类型定义吗? 理想情况下,我希望能够更改“testInput”的类型,并让test在编译时正确推断该类型 public static void Run() { var testInput = 3; var test = ((Func<int, int>) Identity).Compose<int,int,int>(n => n)(testInput); Console.WriteLine(test); } publ

有什么方法可以概括这里的类型定义吗? 理想情况下,我希望能够更改“testInput”的类型,并让test在编译时正确推断该类型

public static void Run()
{
    var testInput = 3;
    var test = ((Func<int, int>) Identity).Compose<int,int,int>(n => n)(testInput);
    Console.WriteLine(test);
}

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;
}
publicstaticvoidrun()
{
var-testInput=3;
var test=((Func)Identity).Compose(n=>n)(testInput);
控制台写入线(测试);
}
公共静态函数组合(此函数f,函数g)
{
返回x=>f(g(x));
}
公共静态T标识(此T值)
{
返回值;
}
更新: 我可以指定传递到Compose中的函数的类型,但这仍然指定了行中的类型

public static void Run()
{
    var testInput = 3;
    var identity = (Func<int, int>) Identity;
    var test = identity.Compose((int n) => n)(testInput);
    Console.WriteLine(test);
}
publicstaticvoidrun()
{
var-testInput=3;
变量标识=(Func)标识;
var测试=身份。组合((int n)=>n)(测试输入);
控制台写入线(测试);
}

一点背景;我正在使用Wes Dyer的

您可以编写一个扩展方法来返回类型的标识函数:

public static Func<T, T> IdentityFunc<T>(this T value)
{
    return (Func<T, T>)Identity;
}

我能得到的最接近的方法是显式键入n=>n lambda的参数:

var test = ((Func<int, int>)Identity).Compose((int n) => n)(testInput);
var test=((Func)Identity).Compose((int n)=>n)(testInput);

我认为你无法实现你的理想;C#类型推断不是这样工作的


你可能会喜欢F#。

好吧,既然我今晚要发短信了,那我就自己试试看。我应该注意到,我不是C#编译器方面的专家,我还没有读过规范(其中任何一篇……任何内容),尽管你链接的那篇文章真的很有趣,但如果我说我是这方面的专家(甚至100%都懂),那我就是在撒谎

除此之外,我对你的问题的看法是:

有什么方法可以概括一下吗 这里的类型定义是什么

我认为简短的答案是否定的。根据提供的信息,C#编译器的类型推断部分根本没有足够的信息从各种变量的使用中推断出足够的信息

正如这里的其他答案所示,它可以简化。您可以使用@Lee的
IdentityFunc
允许使用
var identity
进行类型推断。但是,即使添加了此项,您的示例代码仍然无法推断
Compose
的所有类型变量

想象一下以下情况:

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;
}
在该示例中,在将
c
a
一起使用时,编译器必须追溯推断调用
i.Compose(n=>n)
的返回类型为
Func
。这在C#编译器中显然是不可能的。去掉调用
c(a)
,编译器将不知道
c
的用法,这将消除任何推断
T
的可能性(无论如何它都不能)。一个更高级的类型推断系统可能能够基于泛型返回的使用进行这种推断(可能是F#-另一个我不是专家的主题)

由于Wes Dyer没有提供该特定示例的具体用法,因此不知道他是否使用了其他一些魔法来实现您试图实现的类型推断的程度


像这样更有资格的人将能够为您提供更高级别的细节(以及技术准确性/敏锐性)。我读到他在这里写的一个关于类型推断的问题的很好的回答,但我找不到。他有很多很好的信息。如果你有兴趣,可以试着联系他。此外,他在这里对这个问题的回答讨论了monads(并最终链接到Wes Dyer的文章),你可能有兴趣阅读它:

你能提供更多关于你想要实现什么的具体信息吗?目前,Compose函数的约束过于松散,不允许从lambda中推断T的类型。它根本无法从用法中获得足够的信息。事实上,我没有太多要补充的内容。正如您正确地注意到的,没有lambda参数上的类型,我们没有足够的信息从Compose的调用站点推断T。正如您所注意到的,如果我们可以将分析推迟到合成结果的使用,那么我们可以取得更大的进展,但我们没有这样做。谢谢您对这个问题的出色回答。这个答案显然没有得到应有的支持票。
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;
}
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
}
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>
}