Is there something wrong with the dynamic keyword in C # 4.0?

In dynamic use of C # 4.0 there is a strange behavior:

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 } } 

I am using a Visual Studio 2010 release candidate.

This is mistake? If true, will it be fixed in Release?

+49
c # caching dynamic
Feb 21 '10 at 17:30
source share
4 answers

I can confirm that this is really a mistake. A brief description of what happens here is as follows: in CallBaz, there is one callite that is called three times. This callsite is an InvokeMember because it is the best guess that the compiler can give given the C # syntax, even though it can actually enable GetMember followed by Invoke.

During the second execution of callsite, this is really the binding that the runtime finds. And so it gives a GetMember deferral, followed by a call. The error is that this delay does not limit itself to the case when the argument is an anonymous type. Therefore, in the third execution, the delay is started, and GetMember tries to associate with the program, which, of course, fails.

Thanks for finding this. As Eric points out, we are at a very late stage here, and it becomes difficult for us to fix problems before we set off. But we also want to send the right product. I will do my best to solve this problem, although I will not succeed. If you come up with anything else, feel free to contact me. =)

UPDATE:

Although I can’t guarantee that the final version of VS 2010 and C # 4 will look like when it leaves, I can say that I was able to promote this fix. Today, the escrow build release behaves correctly for your code. Preventing some kind of disaster, you will see that this is fixed upon release. Thanks again. I owe you a beer.

+32
Feb 22 2018-10-22
source share

It is suspicious. I will send him for testing, and we will see what they say.

Just to set expectations: if this is a mistake, and it has not yet been found and fixed, the chances are good, the correction will not get into the final version.

Thanks for getting our attention!

+11
Feb 21 '10 at 23:52
source share

It looks like a serious mistake ...

Note that it works fine if you use ExpandoObject instead of an anonymous type:

 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 } } 

Thus, the problem seems specific to anonymous objects ...

Apparently, in the second call to CallBaz(a) DLR is still trying to access Baz as a property, because this property was anonymous. I suspect the C # middleware does some call resolution caching for better performance, but in this case it clearly broke ...

+8
Feb 21 '10 at 19:05
source share

The same thing happens for me, I suggest you report it here .

+2
Feb 21 '10 at 17:36
source share



All Articles