2016-07-05 152 views
1

我一直认为匿名函数和命名函数一样强大,直到我想将一个私有命名函数变成一个匿名函数,因为只有一个方法体需要调用这个函数。一个简单的例子:匿名函数与非匿名函数一样强大

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]; 

这让我觉得,匿名方法并不像mightly的命名方法 - 至少在一般的使用方面 - 或很我错过了什么?

+0

当然,对于您的例如,LINQ已经为IEnumer定义了一个'.First()'能够' –

回答

1

什么你实际上是试图做的是创造一个一般变量

Func<List<T>, T> getFirst<T> = list => list[0]; 

但不幸的是,这是无效C#作为变量不能通用。只有类型(接口,类,结构),委托和方法可以是通用的。

2

看着this的问题,你可以看到泛型匿名函数在C#中是不可能的。成像时编译器必须处理常规的泛型方法。它实际上为它所要求的每种类型生成一个重载(至少是简单的)。当你用泛型参数声明一个变量时,编译器在这种情况下应该怎么做?它不能用不同的通用参数生成新的变量。

希望这是明确的。你基本上只需要知道泛型方法和类是编译时的东西!

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); 
} 
+0

我很感谢你的回答,但我想摆脱命名的方法,并用C#中不可能的匿名函数来表达它,就像我刚学过的那样。 – David