以 funnc 作为参数的奇怪语法,为什么它有效

本文关键字:语法 参数 为什么 有效 funnc | 更新日期: 2023-09-27 18:31:54

所以我已经使用它一段时间了,我在弄乱它时偶然发现了语法。但我仍然不知道它为什么有效,有人可以向我解释一下吗?这是如何分解的?

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

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

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

更新以修复我在这里输入时意外反转泛型的问题......更新 2:修复了意外定义 arg a T 而不是 Z 的问题

以 funnc<T,Z> 作为参数的奇怪语法,为什么它有效

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

它将Func<T, Z>包装在另一个Func<T, Z>中。 新Func<T, Z>唯一要做的就是在不考虑arg的情况下调用Func<T, Z>

你可以用简单的funcarg => func(arg)换掉arg => func()

方法LoadData是通用的,T其中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)

为了解决第二组伪代码 - 我不相信即使是编译,也不相信你有一个真正的具体例子。您没有满足Tvoid在那里无效。这是一个完美的例子,说明为什么伪代码不是这里问题的好候选者。

它似乎是将一个没有参数的函数"翻译"为一个带参数的函数。第二个重载中的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);
}