C# 4 – It’s a Dynamic World After All

Well after years of maintaining a pure statically type checked face, the C# team is relenting a bit on this stance.  In C# 4.0 you will be able to write code that uses late binding in a much easier way.  Note that VB has had this capability since it shipped.  What this means it the C# gets one new keyword “dynamic” which actually carries static type information (ie just that the associated variable uses runtime binding) and that type information flows throughout your program as you dynamic variables in other places. 

Also, in order to make Office (COM OM) programming easier from C#, they have added support for optional and named parameters.  This makes using certain Office methods that take say 30+ parameters, most of them optional, much easier to invoke from C# 4.  Here’s what these features look like from a very simple usage:

   1: static void Main(string[] args)
   2: {
   3:     // Unlike the type inferencing keyword var which retains compile-time type checking
   4:     // the use of the dynamic keyword tells C# *not* to type check at compile time and
   5:     // let the runtime handle member resolution and invocation.
   6:     dynamic foo = "I'm a string";
   7:  
   8:     // I compile just fine but throw RuntimeBinderException at runtime
   9:     foo.MethodThatDoesntExist();
  10:  
  11:     Method("Hi");
  12:     Method("Hi", ignoreCase: true);
  13:     Method(count: 10, ignoreCase: true, str: "Hi");
  14: }
  15:  
  16: // Optional parameters and named parameters
  17: static void Method(string str, int count = 5, bool ignoreCase = false)
  18: {
  19: }

Note that when you run this program and hit line 9, you get this error:

Here’s the IL for the code above:

   1: private static void Main(string[] args)
   2: {
   3:     object foo = "I'm a string";
   4:     if (<Main>o__SiteContainer0.<>p__Site1 == null)
   5:     {
   6:         <Main>o__SiteContainer0.<>p__Site1 = CallSite<Action<CallSite, object>>.Create(
   7:             new CSharpCallPayload(Microsoft.CSharp.RuntimeBinder.RuntimeBinder.GetInstance(), 
   8:             false, false, "MethodThatDoesntExist", typeof(object), null));
   9:     }
  10:     <Main>o__SiteContainer0.<>p__Site1.Target(<Main>o__SiteContainer0.<>p__Site1, foo);
  11:     Method("Hi", 5, false);
  12:     bool CS$0$0000 = true;
  13:     Method("Hi", 5, CS$0$0000);
  14:     int CS$0$0001 = 10;
  15:     CS$0$0000 = true;
  16:     string CS$0$0002 = "Hi";
  17:     Method(CS$0$0002, CS$0$0001, CS$0$0000);
  18: } 
  19:  
  20:  
  21: private static void Method(string str, 
  22:                            [Optional, DefaultParameterValue(5)] int count, 
  23:                            [Optional, DefaultParameterValue(false)] bool ignoreCase)
  24: {
  25: }

The one thing here I really don’t like is that it appears the “optional” value is being embedded at the call-site (see line 11 above).  This has versioning issues.  I hope I’m wrong about this or the C# team changes this behavior before shipping.  Note that on line 4 you can see the call-site caching that happens for dynamic invocation.  This means that the first dynamic call to this method will be expensive but future invocations (say if this code was called a lot) will be much faster. 

One of the big wins for the C# “dynamic” approach is that it normalizes how you do late binding in C# rather than having different APIs for .NET late binding (aka reflection), COM interop, JavaScript interop (as in Silverlight) and interop with dynamic languages like IronPython and IronRuby.  BTW you can write your own ObjectBinder to plug into C#’s late binding mechanism.  I don’t know any details but they said it could be done.  You can also implement “dynamic” objects in C# by implement IDynamicObject or deriving from DynamicObject.  Dynamic objects in C# don’t participate in compile time member resolution – that is done at runtime.  I can see some interesting uses of this in Mock frameworks.

Advertisements
This entry was posted in CSharp. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s