Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

C# 4.0: Dynamic Programming

0.00/5 (No votes)
18 Apr 2010 1  
The major feature of C# 4.0 is dynamic programming - not just dynamic typing, but dynamic in a broader sense, which means talking to anything that is not statically typed to be a .NET object.

The major feature of C# 4.0 is dynamic programming - not just dynamic typing, but dynamic in a broader sense, which means talking to anything that is not statically typed to be a .NET object.

Dynamic Language Runtime

The Dynamic Language Runtime (DLR) is piece of technology that unifies dynamic programming on the .NET platform, the same way the Common Language Runtime (CLR) has been a common platform for statically typed languages.

The CLR always had dynamic capabilities. You could always use reflection, but its main goal was never to be a dynamic programming environment and there were some features missing. The DLR is built on top of the CLR and adds those missing features to the .NET platform.

Dynamic Language Runtime

The Dynamic Language Runtime is the core infrastructure that consists of:

  • Expression Trees

    The same expression trees used in LINQ, now improved to support statements.

  • Dynamic Dispatch

    Dispatches invocations to the appropriate binder.

  • Call Site Caching

    For improved efficiency.

Dynamic languages and languages with dynamic capabilities are built on top of the DLR. IronPython and IronRuby were already built on top of the DLR, and now, the support for using the DLR is being added to C# and Visual Basic. Other languages built on top of the CLR are expected to also use the DLR in the future.

Underneath the DLR, there are binders that talk to a variety of different technologies:

  • .NET Binder

    Allows to talk to .NET objects.

  • JavaScript Binder

    Allows to talk to JavaScript in SilverLight.

  • IronPython Binder

    Allows to talk to IronPython.

  • IronRuby Binder

    Allows to talk to IronRuby.

  • COM Binder

    Allows to talk to COM.

With all these binders, it is possible to have a single programming experience to talk to all these environments that are not statically typed .NET objects.

The dynamic Static Type

Let’s take this traditional statically typed code:

C#
Calculator calculator = GetCalculator();
int sum = calculator.Sum(10, 20);

Because the variable that receives the return value of the GetCalulator method is statically typed to be of type Calculator and, because the Calculator type has an Add method that receives two integers and returns an integer, it is possible to call that Sum method and assign its return value to a variable statically typed as integer.

Now let's suppose the calculator was not a statically typed .NET class, but, instead, a COM object or some .NET code we don't know the type of. All of a sudden, it gets very painful to call the Add method:

C#
object calculator = GetCalculator();
Type calculatorType = calculator.GetType();
object res = calculatorType.InvokeMember
	("Add", BindingFlags.InvokeMethod, null, calculator, new object[] { 10, 20 });
int sum = Convert.ToInt32(res);

And what if the calculator was a JavaScript object?

C#
ScriptObject calculator = GetCalculator();
object res = calculator.Invoke("Add", 10, 20);
int sum = Convert.ToInt32(res);

For each dynamic domain, we have a different programming experience and that makes it very hard to unify the code.

With C# 4.0, it becomes possible to write code this way:

C#
dynamic calculator = GetCalculator();
int sum = calculator.Add(10, 20);

You simply declare a variable whose static type is dynamic. dynamic is a pseudo-keyword (like var) that indicates to the compiler that operations on the calculator object will be done dynamically.

The way you should look at dynamic is that it’s just like object (System.Object) with dynamic semantics associated. Anything can be assigned to a dynamic.

C#
dynamic x = 1;
dynamic y = "Hello";
dynamic z = new List<int> { 1, 2, 3 };

At run-time, all objects will have a type. In the above example, x is of type System.Int32.

When one or more operands in an operation are typed dynamic, member selection is deferred to run-time instead of compile-time. Then the run-time type is substituted in all variables and normal overload resolution is done, just like it would happen at compile-time.

The result of any dynamic operation is always dynamic and, when a dynamic object is assigned to something else, a dynamic conversion will occur.

CodeResolutionMethod
double x = 1.75;
double y = Math.Abs(x);

compile-time

C#
double Abs(double x)
dynamic x = 1.75;
dynamic y = Math.Abs(x);

run-time

C#
double Abs(double x)
dynamic x = 2;
dynamic y = Math.Abs(x);     

run-time

C#
int Abs(int x)

The above code will always be strongly typed. The difference is that, in the first case the method resolution is done at compile-time, and in the others it’s done at run-time.

IDynamicMetaObjectObject

The DLR is pre-wired to know .NET objects, COM objects and so forth but any dynamic language can implement their own objects or you can implement your own objects in C# through the implementation of the IDynamicMetaObjectProvider interface. When an object implements IDynamicMetaObjectProvider, it can participate in the resolution of how method calls and property access is done.

The .NET Framework already provides two implementations of IDynamicMetaObjectProvider:

  • DynamicObject : IDynamicMetaObjectProvider

    The DynamicObject class enables you to define which operations can be performed on dynamic objects and how to perform those operations. For example, you can define what happens when you try to get or set an object property, call a method, or perform standard mathematical operations such as addition and multiplication.

  • ExpandoObject : IDynamicMetaObjectProvider

    The ExpandoObject class enables you to add and delete members of its instances at run time and also to set and get values of these members. This class supports dynamic binding, which enables you to use standard syntax like sampleObject.sampleMember, instead of more complex syntax like sampleObject.GetAttribute("sampleMember").

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here