使用Func <t,z>作为参数的奇怪语法,为什么它可以工作?</t,z>

时间:2013-09-19 14:21:51

标签: c# .net lambda

所以我已经使用了一段时间了,我在弄乱语法时偶然发现了它。但我仍然不知道为什么它有效,有人可以向我解释一下吗?怎么会被打破?

public T LoadData(Func<Z, T> func, Z arg) where T: class
{
  T data = func(arg);

  return data;
}

public T LoadData(Func<Z, T> func) where T: class
{
  return LoadData<object, T>(arg => func(), null); // <--- Why does the arg => func() part work? It basically ignores the parameter when it gets passed in for some reason...
}

我这样使用它:

public IEnumerable<CategoryTypes> GetCategories()
{
  return LoadData(CategoryProvider.GetCategoriesByGroupId, 12);
}

OR

public IEnumerable<Person> GetStatesLookup()
{
  return LoadData(StatesProvider.GetStates);
}

PS:这是伪代码,我使用它的真正原因比上面的例子更复杂......

更新以修复我在此处输入此内容时意外逆转泛型的问题... 更新2:修复意外定义arg a T而不是Z

4 个答案:

答案 0 :(得分:2)

这是因为您正在创建一个满足Func<T,Z>

的新lambda

答案 1 :(得分:2)

它将Func<T, Z>包裹在另一个Func<T, Z>中。新Func<T, Z>所做的唯一事情是考虑Func<T, Z>来调用旧的arg 没有

您可以使用arg => func()func

换出arg => func(arg)

答案 2 :(得分:2)

方法LoadDataT的通用方法,其中T必须是class。但是,T作为传递给它的Func的单个参数类型进一步传入。最后,Z用作Func的通用返回类型。

简而言之,传入的Func必须与调用LoadData时定义的类型相同。然后它返回一个不同的类型,当然,当您将Func发送到LoadData时,会定义该类型。

所以,这就是为什么这样做的原因:

LoadData(CategoryProvider.GetCategoriesByGroupId, 12);

此情况下的Tint,您传入的Func会收到int类型的单个参数。它返回的是什么,我不知道,但没关系 - 它被用作Z

这个电话可能静态地看起来像这样:

public int LoadData(Func<int, void> func, int arg)

要解决第二组伪代码 - 我不相信即使编译也不相信你有一个真实的具体例子就是这样。您不满意T,而void在那里无效。这是为什么伪代码不适合这里的问题的完美例子。

答案 3 :(得分:0)

似乎是“翻译”一个不带参数的函数到一个函数中。第二个重载中的null可以是任何值,因为它只传递给忽略其参数的函数。

但是,显示的代码没有意义。在第一次重载中,您有:

T data = func(arg);

然而func的返回类型是Z,而不是T。因此,仅当ZT时才会有效。

然后在第二次重载中,调用func时没有参数,但它仍然是Func<T,Z>,这意味着它必须采用单个T参数。

如果交换了类型参数(Z作为参数类型而T作为返回类型),则更有意义,第二个重载不使用Z

public T LoadData(Func<Z,T> func, Z arg) where T: class
{
  T data = func(arg);

  return data;
}

public T LoadData(Func<T> func) where T: class
{
  return LoadData<object, T>(arg => func(), null);
}