C# 4.0: Dynamic Programming
The major feature of C# 4.0 is dynamic programming. Not just dynamic typing, but dynamic in 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.
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.
-
Allows to talk to COM.
Whit 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:
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 lets suppose the calculator was not a statically typed .NET class, but, instead, a COM object or some .NET code we don’t know he type of. All of the sudden it gets very painful to call the Add method:
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?
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:
dynamic calculator = GetCalculator(); int sum = calculator.Add(10, 20);
You simply declare a variable who’s 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.
dynamic x = 1; dynamic y = "Hello"; dynamic z = new List<int> { 1, 2, 3 };
At run-time, all object 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.
Code |
---|
double x = 1.75;
double y = Math.Abs(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 the others it’s done ate 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
<p align="justify">The <strong><a title="DynamicObject Class" href="http://msdn.microsoft.com/library/system.dynamic.dynamicobject.aspx" target="_blank">DynamicObject</a></strong> 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.</p>
-
ExpandoObject : IDynamicMetaObjectProvider
<p align="justify">The <strong><a title="ExpandoObject Class" href="http://msdn.microsoft.com/library/system.dynamic.expandoobject.aspx" target="_blank">ExpandoObject</a></strong> 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 <strong>sampleObject.sampleMember</strong>, instead of more complex syntax like <strong>sampleObject.GetAttribute("sampleMember")</strong>.</p>