Dynamic Programming in C# 4.0 – An Overview

One of the most interesting additions to C# 4.0, I think, is the dynamic addition. Just thinking about this makes me excited. I will jump right into a little theory then some code.

The Theory of Dynamic

So what is this here dynamic thingy? dynamic in C# 4.0 refers to dynamic binding and dynamic binding is what happens at runtime and not at compile time. This involves binding a method, property, operator, member etc of an object at runtime. Yes I know this sounds like polymorphism or like the var keyword or even like using the ultimate base class in C# – object. First and foremost you have to let go or what you know and remember this important fact.

dynamic != var && dynamic != object

The keyword dynamic, casually speaking, tells the compiler that “Even though it cannot resolve the member statically, it should trust the programmer and don’t worry because it will/may be resolved at runtime.”

Code

Here is a sample on how you use the dynamic keyword:

dynamic dyn = “My first time”;
Console.WriteLine(dyn);

Now let’s look at some similarities and differences of var, object, and dynamic for a sec.

var v = 1; // here the compiler will figure out (at compile time) the type for v which will be int.
Console.WriteLine(v.GetType().ToString());
//v.Compute(); // causes a compiler error
object o = 1; // this is boxed from value type to an object with type being int32
Console.WriteLine(o.GetType().ToString());
//o.Compute(); //also gives a compiler error
dynamic d = 1; //type here is int32
Console.WriteLine(d.GetType().ToString());
d.Compute(); // does not give compile time error but will throw a runtime RuntimeBinderException

So how is this binding done?

Look at the following code.

class Program
{

static void Main(string[] args)
{
dynamic dyn = "hello";
Function(dyn); //The first call is slow because here the call site must figure out the binding
Function(dyn); //The second call is faster because all the binding lookup was cached in the first call
Console.Read();
}

public static void Function(string s)
{
Console.WriteLine(s);
}

public static void Function(StringBuilder sb)
{
Console.WriteLine(sb.ToString());
}

}

Which version of Function is called? The one with the string argument.
The call to Function above on the dynamic type is resolved at runtime based on the runtime type information and not on the compile time’s type information. Also, the function with the most specific or closest matching parameter will be the one that is called. Pretty neat huh? By the way, the way in which we used the dynamic keyword above is referred to as language binding

A Bit More Advance Stuff

So let’s say you want to develop a class that has is able to calculate some basic statistics and one of your key requirements is to make it so that the calls to the methods are case insensitive. Also, you want to be able to add new functionality at will. How can you do that?
In the System.Dynamic namespace there is a class called DynamicObject that implements IDynamicMetaObjectProvider. If you want your classes to have the dynamic capability, then inheriting this class gives you those capabilities. By the way, inheriting DynamicObject or implementing IDynamicMetaObjectProvider is called custom binding.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Dynamic;

namespace OliverCode.DynamicProgramming
{
public class Statistics : DynamicObject
{
private readonly double[] _arrayOfValues;

public Statistics(double[] arrVals)
{
_arrayOfValues = arrVals;
}

public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
bool isSuccess = true;

switch (binder.Name.ToLower())
{
case "average":
result = _arrayOfValues.Average();
break;
case "max":
result = _arrayOfValues.Max();
break;
case "min":
result = _arrayOfValues.Min();
break;
default:
result = 0;
isSuccess = false;
break;
}

return isSuccess;
}
}

class Program
{

static void Main(string[] args)
{
dynamic stats = new Statistics(new double[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });

Console.WriteLine(stats.max()); //resolved at runtime time
Console.WriteLine(stats.Max());//resolved at runtime time
Console.WriteLine(stats.Mean());//resolved at runtime time

Console.Read();
}
}
}

Pay attention to the TryInvokeMember method which has been overridden. This means that my class can handle method calls. Actually there are a few methods that you can override:

IEnumerable GetDynamicMemberNames();
DynamicMetaObject GetMetaObject(Expression parameter);
bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result);
bool TryConvert(ConvertBinder binder, out object result);
bool TryCreateInstance(CreateInstanceBinder binder, object[] args, out object result);
bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes);
bool TryDeleteMember(DeleteMemberBinder binder);
bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result);
bool TryGetMember(GetMemberBinder binder, out object result);
bool TryInvoke(InvokeBinder binder, object[] args, out object result);
bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result);
bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value);
bool TrySetMember(SetMemberBinder binder, object value);
bool TryUnaryOperation(UnaryOperationBinder binder, out object result);

I don’t have the details on all the methods but you get the gist.

So when does dynamic not work?

As far as I know there are 3 cases in which dynamic doesn’t work

  1. On interface members that are explicitly implemented
  2.  With Extension methods
  3. Classes that subclass a base class but hide the bas classes members

So there is your introduction to dynamic programming. Now go code and don’t forget to live.

Advertisements

3 thoughts on “Dynamic Programming in C# 4.0 – An Overview

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