generics - 泛型类型的扩展方法,带有额外的泛型类型参数

标签 generics extension-methods type-inference

我想为泛型类型编写一个扩展方法,并带有额外的泛型类型参数。我已经有工作代码,但不喜欢结果,因为要求用户重新输入现有类型的泛型类型参数。

我有一个具体的例子,但请记住,这是一个普遍的问题。我感谢手头的特定问题的反馈,但我正在寻找通用的解决方案。

对于一类类型 Action<T> , 添加一个具有类似于此签名的扩展方法:

Func<T, TResult> ToFunc<TResult>();

这是我的工作代码:
public static class DelegateExtensions
{
  public static Func<T, TResult> ToFunc<T, TResult>(this Action<T> action)
  {
    return arg => { action(arg); return default(TResult); };
  }
}

但用法很臭:
public void TakesAFunc(Func<int, float> someFunc) { /* ... */ }
// ...
Action<int> someIntAction = /* ... */;
TakesAFunc(someIntAction.ToFunc<int, float>());

在本例中,int泛型参数是唯一可接受的值,因此会导致不必要的代码重复。

类型推断在这里不起作用。我认为这是因为您无法通过返回类型推断泛型参数。

这段代码可以解决问题,但不幸的是似乎不起作用:
public static class DelegateExtensions<T>
{
  public static Func<T, TResult> ToFunc<TResult>(this Action<T> action)
  {
    return arg => { action(arg); return default(TResult); };
  }
}

用法与您期望的完全一样:
public void TakesAFunc(Func<int, float> someFunc) { /* ... */ }
// ...
Action<int> someIntAction = /* ... */;
TakesAFunc(someIntAction.ToFunc<float>());

我注意到 System.Linq.Queryable以我的第一段代码的方式工作,尽管它通常不需要额外的类型参数,因此类型推断有效。

是否有任何已知的技巧可以绕过要求这些重复的泛型类型参数?我想到的一个想法是代码生成器或某种宏,但我想不出如何干净利落地做到这一点。

最佳答案

这种事情的一个常见技巧是传递所需类型的虚拟值,仅用于类型推断,这在涉及匿名类型的某些场景中是必需的。

public static class DelegateExtensions
{
  public static Func<T, TResult> 
  ToFunc<T, TResult>(this Action<T> action, TResult ignored)
  {
    return arg => { action(arg); return default(TResult); };
  }
}

这是一个多么好的技巧取决于个人意见,但是每次我调用它以及每次我回到我调用它的地方时,这都会使我感到困惑。您还可以更改方法的语义,使第二个参数成为返回值,从而允许调用者决定是否需要默认值。

至于你的第二个例子,我很确定泛型类型不允许使用扩展方法,但我没有方便的链接

关于generics - 泛型类型的扩展方法,带有额外的泛型类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4456609/

相关文章:

java - Java 中泛型的深拷贝

generics - 编译器覆盖 F# 中的类型定义(泛型)

java - 什么时候在 Java 中进行类型检查

c++ - (Visual-)字符串文字的 C++ 模板类型推断 - VS 2010 与 VS 2017

c# - NRules:在具有自定义基类的规则上使用 DSL 扩展的问题

ruby - 在运行时获取/设置 Ruby 方法元数据的最佳策略是什么?

java - 通用类型参数的 T、U、V 约定从何而来?

ios - 使用 switch 语句创建泛型函数,该函数根据传入参数的类型执行不同的代码

c# - 泛型和 IComparable - 错误 CS00301

c# - 扩展方法中的两种泛型类型