C# 匿名函数与非匿名函数一样强大
我一直认为匿名函数和命名函数一样强大,直到我想把一个私有命名函数变成一个匿名函数,因为只有一个方法体需要调用这个函数。一个简单的例子:C# 匿名函数与非匿名函数一样强大,c#,generics,C#,Generics,我一直认为匿名函数和命名函数一样强大,直到我想把一个私有命名函数变成一个匿名函数,因为只有一个方法体需要调用这个函数。一个简单的例子: public void Init(List<int> numbers, List<string> texts) { int n = GetFirst(numbers); string t = GetFirst(texts); } private T GetFirst<T>(List<T> list) {
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];
}
但是我只能用定义的泛型参数来实例化它
GetFirstDelegate<string> getFirst = list => list[0];
GetFirstDelegate getFirst=list=>list[0];
但与占位符通用参数不同:
GetFirstDelegate<T> getFirst = list => list[0];
GetFirstDelegate getFirst=list=>list[0];
这让我觉得匿名方法不如命名方法强大——至少在泛型用法方面是如此——或者我遗漏了什么吗?看看这个问题,你可以看到泛型匿名函数在C#中是不可能的。当编译器必须使用常规泛型方法时进行映像。它实际上为它所调用的每种类型生成一个重载(至少简单地说)。当您使用泛型参数声明变量时,编译器在这个实例中应该如何做?它无法生成具有不同泛型参数的新变量
希望这是清楚的。您基本上只需要知道泛型方法和类是编译时的事情 您实际要做的是创建一个类似的通用变量
Func<List<T>, T> getFirst<T> = list => list[0];
Func getFirst=list=>list[0];
但不幸的是,这是无效的,因为变量不能是泛型的。只有类型(接口、类、结构)、委托和方法可以是泛型的。接受
List
作为输入并返回T
的函数的签名是Func
,而不是Func
我想这就是你想要的:
private Func<List<T>, T> GenGetFirst<T>()
{
return list => list[0];
}
private Func GenGetFirst()
{
返回列表=>list[0];
}
用法:
public void Init(List<int> numbers, List<string> texts)
{
int n = GenGetFirst<int>()(numbers);
string t = GenGetFirst<string>()(texts);
}
public void Init(列表编号、列表文本)
{
int n=GenGetFirst()(数字);
字符串t=GenGetFirst()(文本);
}
或者以更清晰的方式:
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);
}
public void Init(列表编号、列表文本)
{
Func intFunc=GenGetFirst();
Func stringFunc=GenGetFirst();
int n=int func(数字);
字符串t=stringFunc(文本);
}
当然,以你的例子来说,LINQ已经为IEnumerable
定义了一个.First()
,我很感激你的回答,但我想摆脱命名方法,用一个匿名函数来表达它,这在C语言中是不可能的,就像我刚刚学到的那样。
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);
}