泛型类型的扩展方法,带有附加的泛型类型参数
我想为泛型类型编写一个扩展方法,并带有附加的泛型类型参数。我已经有了工作代码,但不喜欢结果,因为用户需要重新输入现有类型的泛型类型参数。
我有一个具体的例子,但请记住这是一个普遍问题。我很感谢有关当前特定问题的反馈,但我正在寻找通用解决方案。
对于 Action
类型的类,添加一个具有类似于以下签名的扩展方法:
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
的工作方式与我的第一块代码的工作方式相同,尽管它通常不需要额外的类型参数,所以类型推断是有效的。
是否有任何已知的技巧可以解决需要这些重复的泛型类型参数的问题?我想到的一个想法是代码生成器或某种宏,但我想不出如何干净利落地做到这一点。
I would like to write an extension method for a generic type, with additional generic type parameters. I have working code already, but don't like the result, because the user is required to re-enter the generic type parameters of the existing type.
I have a concrete example, but keep in mind that this is a general problem. I appreciate feedback on the particular problem at hand, but I am looking for general solutions.
For a class of type Action<T>
, add an extension method with a signature similar to this:
Func<T, TResult> ToFunc<TResult>();
Here's my working code:
public static class DelegateExtensions
{
public static Func<T, TResult> ToFunc<T, TResult>(this Action<T> action)
{
return arg => { action(arg); return default(TResult); };
}
}
But the usage stinks:
public void TakesAFunc(Func<int, float> someFunc) { /* ... */ }
// ...
Action<int> someIntAction = /* ... */;
TakesAFunc(someIntAction.ToFunc<int, float>());
In this example, the int
generic parameter is the only value that is acceptable, so it causes unnecessary code duplication.
Type inference does not work here. I think this is because you can't infer a generic parameter via return type.
This code would solve the problem, but unfortunately does not seem to work:
public static class DelegateExtensions<T>
{
public static Func<T, TResult> ToFunc<TResult>(this Action<T> action)
{
return arg => { action(arg); return default(TResult); };
}
}
Usage would be exactly like you'd expect:
public void TakesAFunc(Func<int, float> someFunc) { /* ... */ }
// ...
Action<int> someIntAction = /* ... */;
TakesAFunc(someIntAction.ToFunc<float>());
I noticed that System.Linq.Queryable
works the way my first chunk of code does, though it usually doesn't need extra type parameters, so type inference works.
Is there any known trick to get around requiring these duplicate generic type parameters? One thought that comes to mind would be code generators or macros of some sort, but I can't think of how I'd do it cleanly.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
处理这类事情的一个常见技巧是传递所需类型的虚拟值以进行类型推断,这在涉及匿名类型的某些场景中是必需的。
这个技巧有多好取决于个人意见,但是每次我调用它以及每次我回到我调用它的地方时,这都会让我感到困惑。您还可以更改该方法的语义,使第二个参数成为返回值,从而允许调用者决定是否需要默认值。
至于你的第二个例子,我很确定泛型类型不允许扩展方法,但我没有方便的链接
One common trick for this sort of thing is to pass a dummy value of the desired type just for type inference, which is required in certain scenarios involving anonymous types.
How good of a trick this is is up to personal opinion, but this would confuse me every time I called it and every time I came back to a place that I called it. You could also change the semantics of the method to make the second parameter be the return value, allowing the caller to decide if they want the default value or not.
As to your second example, I'm pretty sure extension methods are not allowed on generic types, but I don't have a link handy
我参加聚会迟到了——抱歉。
正如已经提到的 - 如果不将 Func 切换到输出参数,目前这是不可能的。
我将抛出另一种方法来完成此类事情 - 它看起来有点流畅的语法,但它有效。
然后调用它:
这并不完全是您想要的,但它实现了不再声明 int 泛型的目标,并且可以扩展到您想做类似事情的其他情况。
I am late to the party - sorry.
As has been mentioned - this is not currently possible with out switching the Func to an out param.
I'll throw out another way to do this sort of thing - it gets to look a bit fluid syntax like, but it works.
Then calling it goes:
This is not exactly what you wanted, but it achieves the goal of not stating the int generic again and can be extended to other cases where you want to do something similar.