我一直认为匿名函数和命名函数一样强大,直到我想将私有命名函数转换为匿名函数,因为只需要一个方法体调用此函数。一个简单的例子:
public void Init(List<int> numbers, List<string> texts)
{
int n = GetFirst(numbers);
string t = GetFirst(texts);
}
private T GetFirst<T>(List<T> list)
{
return list[0];
}
希望定义像
这样的东西GenFunc<T, List<T>, T> getFirst = list => list[0];
并使用它而不是实例方法GetFirst
。使用Func
是不可能的,因为通用参数具有不同的语义。因此,我定义了一个代表(Func
)的“基础”
delegate T GetFirstDelegate<T>(List<T> list);
但我只能用定义的通用参数来实例化它,例如
GetFirstDelegate<string> getFirst = list => list[0];
但不是我希望使用占位符泛型参数:
GetFirstDelegate<T> getFirst = list => list[0];
这让我觉得匿名方法不像命名方法那样 - 至少在通用用法方面 - 或者我错过了什么?
答案 0 :(得分:2)
查看this问题,您可以看到C#中无法使用通用匿名函数。编译器与常规泛型方法有关时的映像。它实际上为它所调用的每种类型生成一个重载(至少是简单的)。使用泛型参数声明变量时,编译器应如何在此实例中执行此操作?它不能生成具有不同通用参数的新变量。
希望这很清楚。您基本上只需知道泛型方法和类是编译时的事情!
答案 1 :(得分:1)
您实际要做的是创建通用变量,就像那样
Func<List<T>, T> getFirst<T> = list => list[0];
但不幸的是,这是无效的C#,因为变量不能是通用的。只有类型(接口,类,结构),委托和方法可以是通用的。
答案 2 :(得分:0)
接受List<T>
作为输入并返回T
的函数的签名为Func<List<T>, T>
而不是Func<T, List<T>, T>
。
我认为这就是你想要的:
private Func<List<T>, T> GenGetFirst<T>()
{
return list => list[0];
}
<强>用法:强>
public void Init(List<int> numbers, List<string> texts)
{
int n = GenGetFirst<int>()(numbers);
string t = GenGetFirst<string>()(texts);
}
或者采用更强烈的清晰方式:
public void Init(List<int> numbers, List<string> texts)
{
Func<List<int>, int> intFunc = GenGetFirst<int>();
Func<List<string>, string> stringFunc = GenGetFirst<string>();
int n = intFunc(numbers);
string t = stringFunc(texts);
}