请考虑以下示例程序:
using System;
public delegate string MyDelegateType(int integer);
partial class Program
{
static string MyMethod(int integer) { return integer.ToString(); }
static void Main()
{
Func<int, string> func = MyMethod;
// Scenario 1: works
var newDelegate1 = new MyDelegateType(func);
newDelegate1(47);
// Scenario 2: doesn’t work
dynamic dyn = func;
var newDelegate2 = new MyDelegateType(dyn);
newDelegate2(47);
}
}
Run Code Online (Sandbox Code Playgroud)
第一个按预期工作 - 转换MyDelegateType成功.但是,第二个会抛出一条RuntimeBinderException错误消息:
无法将类型'System.Func <int,string>'隐式转换为'MyDelegateType'
C#规范中是否存在允许此行为的任何内容,或者这是Microsoft C#编译器中的错误?
Eri*_*ert 16
好抓Timwi.
我们对动态方法组的支持很弱.例如,考虑这个更简单的情况:
class C
{
public void M() {}
}
class P
{
static void Main()
{
dynamic d = new C();
C c = new C();
Action a1 = c.M; // works
Action a2 = d.M; // fails at runtime
Run Code Online (Sandbox Code Playgroud)
它d.M被动态运行时解释为属性get(或字段访问),当它作为方法组解析时,它在运行时失败.
同样的事情发生在你的情况下,它只是有点模糊.当你说MyDelegate x = new MyDelegate(someOtherDelegate);编译器对待它时就像你说的那样MyDelegate x = someOtherDelegate.Invoke;.动态运行时块不知道要进行那种转换,即使它确实如此,它也无法处理解析.Invoke作为表达式部分结果的方法组.
C#规范中是否存在允许此行为的任何内容,或者这是Microsoft C#编译器中的错误?
规范没有提到这应该是运行时错误,并且暗示它应该在运行时正确处理; 显然,实施不会这样做.虽然这是实施的一个缺点,但我不会称之为"错误",因为我们故意制造了你发现的行为.我们没有资源让这些表达式完全正确,所以我们将它们留作错误.如果我们在动态运行时中获得表示方法组的好方法,我们可能会实现它.
类似地,动态代码中没有办法表示"这个动态的东西是一个lambda表达式,其中参数的类型将在运行时确定".如果我们有一个很好的方式来代表未来的人,我们可能会做这项工作.
山姆在2008年谈到了这个问题; 看他的文章:
http://blogs.msdn.com/b/samng/archive/2008/11/02/dynamic-in-c-ii-basics.aspx