.NET4:如何将动态绑定应用于带返回的匿名委托?
class MyClass
{
public event Action<string> OnAction;
public event Func<string, int> OnFunc;
}
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
/// I need to handle arbitrary events.
/// But I see no way to create anonymous delegates in runtime
/// with arbitrary returns and parameters. So I choosed to
/// create multiple “signatures” with different parameter
/// number (up to 10) and different returns (either the Action or
/// Func). While Actions<> work pretty well, the Funcs<> do not.
Action<dynamic> someAction = delegate(dynamic p1) { };
Func<dynamic, dynamic> someFunc = delegate(dynamic p1) { return 42;};
// OK
mc.OnAction += someAction;
// Error: “Cannot implicitly convert type 'System.Func<dynamic,dynamic>'
// to 'System.Func<string,int>'”
mc.OnFunc += someFunc;
// It doesn't work this way as well (the same error message):
// dynamic someFunc = new Func<dynamic, dynamic>((dynamic n1) => { return 42; });
// Let's try another way
// 1:
// Cannot convert anonymous method to delegate type 'System.Func<string,int>'
// because the parameter types do not match the delegate parameter types.
// 2 (even more funny):
// Parameter 1 is declared as type 'dynamic' but should be 'string'.
mc.OnFunc += delegate(dynamic p1) { return 42; };
}
}
为什么它适用于操作而不适用于函数? 换句话说,我只是想知道为什么 Action
可以,而 Func
不是。谢谢。
class MyClass
{
public event Action<string> OnAction;
public event Func<string, int> OnFunc;
}
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
/// I need to handle arbitrary events.
/// But I see no way to create anonymous delegates in runtime
/// with arbitrary returns and parameters. So I choosed to
/// create multiple “signatures” with different parameter
/// number (up to 10) and different returns (either the Action or
/// Func). While Actions<> work pretty well, the Funcs<> do not.
Action<dynamic> someAction = delegate(dynamic p1) { };
Func<dynamic, dynamic> someFunc = delegate(dynamic p1) { return 42;};
// OK
mc.OnAction += someAction;
// Error: “Cannot implicitly convert type 'System.Func<dynamic,dynamic>'
// to 'System.Func<string,int>'”
mc.OnFunc += someFunc;
// It doesn't work this way as well (the same error message):
// dynamic someFunc = new Func<dynamic, dynamic>((dynamic n1) => { return 42; });
// Let's try another way
// 1:
// Cannot convert anonymous method to delegate type 'System.Func<string,int>'
// because the parameter types do not match the delegate parameter types.
// 2 (even more funny):
// Parameter 1 is declared as type 'dynamic' but should be 'string'.
mc.OnFunc += delegate(dynamic p1) { return 42; };
}
}
Why does it work for actions and doesn't for functions?
In other words, I just would like to know why Action<dynamic> → Action<string>
is ok while Func<dynamic,dynamic> → Func<string, int>
is not. Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Action 和 Func 定义之间的唯一区别是 Action 没有返回类型。如果您将代码从: 更改
为
它就可以了。
The only difference between your Action and Func definitions is Action has no return types. If you change your code from:
to
It works.
好的,我明白了。
该操作定义如下:
delegate void Action; (T arg);
,而 func 是这样的:delegate TResult Func; (T arg);
问题出在 out 关键字中,它表示协变,但不像 in 关键字那样表示逆变。同时typeof(dynamic) == typeof(object)
为 true。因此,动态作为一种更通用的类型,与我们所采用的任何内容都不协变。嗯,我认为动态绑定更灵活。“进一步阅读:链接
顺便说一句,我后来在那里找到的引用:
Ok, I got it.
The action is defined as follows:
delegate void Action <in T> (T arg);
, while the func is like this:delegate TResult Func <in T, out TResult> (T arg);
The problem is in out keyword, which indicates covariance but not contravariance as in keyword does. At the same timetypeof(dynamic) == typeof(object)
is true. So dynamic, as a more general type, isn't covariant to whatever we take. Hmm, I thought dynamic binding is more flexible.“Further reading: Link
Btw, the quote I found there afterwards:
如果 C# 需要返回类型为
int
的委托,则声明返回dynamic
的委托是不兼容的。您的委托被声明为Func
,并且 C# 是强类型的。它并不关心你的函数是否实际上返回一个 int 并接受一个字符串;它仍然被声明为Func
。如果您考虑以下示例,代码无法编译的原因是显而易见的:
If C# is expecting a delegate with a return type of
int
, a delegate declared to returndynamic
is incompatible. Your delegate is declared asFunc<dynamic, dynamic>
, and C# is strongly-typed. It doesn't care if your function actually returns an int and takes a string; it's still declared asFunc<dynamic, dynamic>
.The reason why the code doesn't compile is obvious if you consider this example: