在C#4.0中的dynamic关键字有问题吗?

C#4.0dynamic用法有一些奇怪的现象:

using System; class Program { public void Baz() { Console.WriteLine("Baz1"); } static void CallBaz(dynamic x) { x.Baz(); } static void Main(string[] args) { dynamic a = new Program(); dynamic b = new { Baz = new Action(() => Console.WriteLine("Baz2")) }; CallBaz(a); // ok CallBaz(b); // ok CallBaz(a); // Unhandled Exception: // Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: // The name 'Baz' is bound to a method and cannot be used like a property } } 

我正在使用Visual Studio 2010 Release Candidate。

这是一个错误? 如果这是真的,它会在发行版中修复吗?

我可以证实这确实是一个错误。 这里有什么错误的快速描述如下:在CallBaz,有一个调用三次的调用网站。 该callsite是一个InvokeMember,因为这是编译器在C#语法下可以做出的最好的猜测,尽pipe它实际上可以parsing为一个GetMember,然后是一个Invoke。

在调用站点的第二次执行期间,这确实是运行时发现的绑定。 所以它会产生延迟到一个GetMember,然后调用。 问题在于,这个延期并没有把自己限制在参数是匿名types的情况下。 因此,在第三次执行中,推迟开始并且GetMember尝试绑定到程序,当然这失败了。

感谢您find这个。 正如Eric所指出的那样,我们现在处于一个非常晚期的阶段,在我们发货之前就已经很难解决问题了。 但是我们也想要发运正确的产品。 我会尽我所能去解决这个问题,尽pipe我可能不会成功。 如果你想出其他的东西,请随时与我联系。 =)

更新:

虽然我无法保证VS 2010和C#4的最终版本在发布时会是什么样子,但我可以说我已经成功推进了这个修复。 今天的版本托pipe构build行为正确的代码。 除非发生一些灾难,否则你会在发布时看到这一点。 再次感谢。 我欠你一杯啤酒。

看起来很可疑。 我会把它发送到testing,我们会看到他们说什么。

只是为了设定期望:如果这是一个错误,而且还没有被发现和修复,赔率是很好的修复不会进入最终版本。

谢谢让我们注意到这个!

这看起来像一个严重的错误…

请注意,如果您使用ExpandoObject而不是匿名types,则工作正常:

 using System; using System.Dynamic; class Program { public void Baz() { Console.WriteLine("Baz1"); } static void CallBaz(dynamic x) { x.Baz(); } static void Main(string[] args) { dynamic a = new Program(); dynamic b = new ExpandoObject(); b.Baz = new Action(() => Console.WriteLine("Baz2")); CallBaz(a); // ok CallBaz(b); // ok CallBaz(a); // ok } } 

所以这个问题似乎特定于匿名对象…

显然,在第二次调用CallBaz(a) ,DLR仍然尝试访问Baz作为属性,因为它是匿名types的属性。 我怀疑,C#活页夹做了一些呼叫parsingcaching,以获得更好的性能,但在这种情况下,它显然是破碎的…

同样的事情发生在我身上,我build议你在这里报告。