首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >泛型类型的扩展方法,带有附加的泛型类型参数

泛型类型的扩展方法,带有附加的泛型类型参数
EN

Stack Overflow用户
提问于 2010-12-16 09:17:06
回答 2查看 579关注 0票数 4

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

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

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

代码语言:javascript
运行
复制
Func<T, TResult> ToFunc<TResult>();

下面是我的工作代码:

代码语言:javascript
运行
复制
public static class DelegateExtensions
{
  public static Func<T, TResult> ToFunc<T, TResult>(this Action<T> action)
  {
    return arg => { action(arg); return default(TResult); };
  }
}

但是它的用法很糟糕:

代码语言:javascript
运行
复制
public void TakesAFunc(Func<int, float> someFunc) { /* ... */ }
// ...
Action<int> someIntAction = /* ... */;
TakesAFunc(someIntAction.ToFunc<int, float>());

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

类型推断在这里不起作用。我想这是因为你不能通过返回类型来推断一个泛型参数。

这段代码可以解决这个问题,但不幸的是似乎不起作用:

代码语言:javascript
运行
复制
public static class DelegateExtensions<T>
{
  public static Func<T, TResult> ToFunc<TResult>(this Action<T> action)
  {
    return arg => { action(arg); return default(TResult); };
  }
}

用法将与您预期的完全相同:

代码语言:javascript
运行
复制
public void TakesAFunc(Func<int, float> someFunc) { /* ... */ }
// ...
Action<int> someIntAction = /* ... */;
TakesAFunc(someIntAction.ToFunc<float>());

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

有什么已知的技巧可以绕过这些重复的泛型类型参数吗?脑海中浮现的一个想法是代码生成器或某种宏,但我想不出如何才能干净利落地做到这一点。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-12-16 13:22:35

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

代码语言:javascript
运行
复制
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); };
  }
}

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

至于您的第二个示例,我非常确定泛型类型上不允许使用扩展方法,但我手边没有链接

票数 3
EN

Stack Overflow用户

发布于 2011-01-11 12:31:40

我参加聚会迟到了--对不起。

如前所述-如果没有将Func切换到out参数,这目前是不可能的。

我将抛出另一种方法来做这类事情-它看起来有点流畅的语法,但它是有效的。

代码语言:javascript
运行
复制
 public class ActionWrap<T>
{
    private readonly Action<T> _action;

    internal ActionWrap(Action<T> action)
    {
        _action = action;
    }

    public Func<T, TResult> OfType<TResult>()
    {
        return arg => { _action(arg); return default(TResult); };
    }
}

public static class DelegateExtensions
{
    public static ActionWrap<T> ToFunc<T>(this Action<T> action)
    {
        return new ActionWrap<T>(action);
    }
}

那么调用它就是:

代码语言:javascript
运行
复制
Action<int> x = z=> Console.WriteLine(z);
Func<int, float> asFunc = x.ToFunc().OfType<float>();

这并不完全是您想要的,但它实现了不再声明int泛型的目标,并且可以扩展到您想要做类似事情的其他情况。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4456609

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档