匿名函数与非匿名函数一样强大

时间:2016-07-05 12:23:12

标签: 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)
{
  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];

这让我觉得匿名方法不像命名方法那样 - 至少在通用用法方面 - 或者我错过了什么?

3 个答案:

答案 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);
}