Toying with the C# 4.0



Dynamic - The dynamic keyword

As almost .net community people know, the .Net 4.0 introduced many features like the optional and named parameters, the covariance, the countravariance and the dynamic which is a new introduced type that comes with serveral advantages. Frankly, I wasn't convinced by this special kind of object from the beginning and I had some doubts about this for many reasons such as the utility of that kind of object, the benefit of using that kind of dynamic programming as the reflection can do perfectly the job, the raison of ignoring the compiler and the compile time as it could help us to detect program bugs earlier and at last but not least the impact of this kind of programming on the objet inheritance and the polymorphism case. So I tried to parse this kind of object to see what are the benefits and what are the limits. In this article, I will expose those two issues not through the theorist manners but through real cases via some implementation techniques.

First, let's begin by introducing the DLR Dynamic Language Runtime.

1. Introduction to the Dynamic Language Runtime:

At the contrast of the idea that might people have, the DLR unit is neither a dependent component that runs within the Common Language Runtime nor a new added component to the .Net Framwork at the core level. It is built upon both the .Net Framework kernel and the Common Language Runtime like the rest of the assemblies, I mean System.IO, System.Reflection and the others. The DLR is presented by the System.Dynamic namespace. The purpose of that component is to primary bring support to dynamic languages like IronRubby and IronPhyton and dealing with unknown objects structures at the run time such as dealing with DOM Document Object Model cases where the structure of a given XML unit is not known in advance. The DLR reprsents the same aim as the equivalent in the Java world ,I mean the Da vinci Machine which extends the Java Virtual Machine to enable deal dynamically with objects and dynamic languages environements.

2.The dynamic vs. the object keyword

First of all, it is necessary to have visual studio 2010 and .Net framework 4.0 to start programming with dynamic objects. It is possible to download an express version from this link http://www.microsoft.com/express/downloads/.
Let's create a simple console application to start test this object type.

        class Program
        {
            static void Main(string[] args)
            {
                //t is type of dynamic
                dynamic t = 2;
                Console.WriteLine(" Current assignement: {0} is {1}\r\n", t, t.GetType());
                //t is now accepting a string
                t = "Bechir";
                Console.WriteLine("Current assignement: {0} is {1}\r\n", t, t.GetType());
                //t is now accepting a person
                t = new Person { Name = "Bechir" };
                Console.WriteLine("Current assignement: {0} is {1}\r\n", t, t.GetType());
                Console.Read();
            }
        }
        public class Person
        {
            public string Name { get; set; }
        }

As you can see, the t dynamic variable here can accept any kind of type as assignment. Well, the question that could be asked in this context is what's the new as the object type is also doing the same thing by accepting any kind of assignment?

If we try to change the keyword dynamic by object and try to explore the intermediate language represented by the bellow figure 1.We run the ildasm.exe with the command /metadata against the executing assembly and we try to explore the main method IL code.

Figure1.gif

figure 1

In the figure 1, it is clear that the type t is defined as an instance of type object so the compiler knows it well. But if now we substitute the object keyword by dynamic and run the ildasm /metadata again against our assembly and start parsing again the main method instructions stack, we can remark that the instance type of object is no longer present. Instead of that, we can find a generic class called CallSite<> that belongs to the System.Runtime.CompilerServices namespace as shown in the figure 2.

figure2.gif

Figure 2

This class plays the role of the intermediate between the caller and the new runtime created object. As the compiler doesn't know about that object and what is going to be at the runtime. The code is not emited according to the classic way but it is encapsulated as an expression tree (notion borrowed from System.Linq.Expressions) that holds necessary data to help resolve the correct object and bind it appropriatly at runtime. This will happen instead of emitting the IL Intermediate Language as usually.

Although the CallSite<> class is exposed to the final user, it is not necessary to make use of it directly from the code. It is rather used internaly by the compiler.

As a conclusion for this section, althought the code behaviour appears as the same, the way that the compiler deals with and the manner that objects are created differs completely from dynamic to object.

3.The dynamic vs. the var keyword

Almost .Net community people know that C# 3.0 introduced the keyword var which helps us create implicit strongly typed objects, and that is particularly useful when dealing with linq.

Let's try to substitute the dynamic keyword by var keyword and see what's happening.

A compile time error is raised at compile time, although that var keyword gives an impression that this is generic as same as object type, this is a wrong impression as the result is illustrated by those two compiler errors

figure3.gif

Figure3

If we try to modify the code a little

        class Program
        {
            static void Main(string[] args)
            {
                //t is now accepting a person
                var t = new { Name = "Bechir" };
                Console.WriteLine("Current assignement: {0} is {1}\r\n", t, t.GetType());
                Console.Read();
            }
        }

And then run the ildasm /metadata against the executing assembly to see the generated intermediate language.

figure4.gif

Figure 4

The compiler behavior is now different when comparing with the previous cases. It creates an anonymous Type with a reference 0 at the compile time in order to wrap up our anonymous object at the difference to the dynamic case where the compiler doesn't know any thing about our object and leave this job to the CallSite<> and the runtime binder.

As a conclusion for this section, the var keyword is totaly different when comparing with the dynamic one as the first type declared with the var keyword is resolved at the compile time as same as the other explecit strongly typed objects. And once that object is assigned, it couldn't accept subsequent assignements of differents types.

4.The dynamic method dispatch paradigm

To understand well the issue let's suppose this case. First suppose this pattern:

        public class Base
        {
            public virtual void InstanceMethod()
            {
                Console.WriteLine("The base class method is called");
            }
        }
        public class FirstClass : Base
        {
            public override void InstanceMethod()
            {
                Console.WriteLine("The first class method is called");
            }
        }
        public class SecondClass : Base
        {
            public override void InstanceMethod()
            {
                Console.WriteLine("The second class method is called");
            }
        }
        public class ThirdClass : Base
        {
            public override void InstanceMethod()
            {
                Console.WriteLine("The third class method is called");
            }
        }

To explain a little this above pattern, we can say that this class that we called Base serves as a base class for the first, second and the third class. An invoker class which plays the role of visitor (Visitor pattern) will invoke the corresponding method of the given class

        class Invoker
        {
            public void Method(Base instance)
            {
                instance.InstanceMethod();
            }
        }

Inspite of the fact that the defined argument is type of Base in the above method (Method), the right method (InstanceMethod) will be invoked if a given derived class (the first, the second or the third class) is used as an argument at the method level as the compiler will detect at compile time which method to invoke based on the derived instance member type.

Thus, for example, if we run the bellow code:

            Invoker dummy = new Invoker();
            SecondClass secondclass = new SecondClass();
            dummy.Method(secondclass);
            Console.Read();
The result will be "The second class method is called". This mecanism is called single dispatch, it is the one where the compiler will comit to a given member at compile time which is type of second class in this case.

Now imagine this case:

        public class FirstClass
        {
            public void InstanceMethod()
            {
                Console.WriteLine("The first class is invoked");
            }
        }
        public class SecondClass
        {
            public void InstanceMethod()
            {
                Console.WriteLine("The second class is invoked");
            }
        }
        public class ThirdClass
        {
            public void InstanceMethod()
            {
                Console.WriteLine("The third class is invoked");
            }
        }

Although the three classes implement the same method signature for the (InstanceMethod), they didn't have an explicit relationship like inheritance or even polymorphism through interfaces. In this case, if we try to use the invoker class as a visitor we will fall down into a serious pattern case.

class Invoker
{
public void Method(?!!!! instance)
{
instance.InstanceMethod();
}
}

As we can observe, the issue is what can one put as an argument in this case? Hence, the compiler won't be able to determine which argument type to use.

if we try this bellow implementation, then we fail to call the InvokeMethod as it is not a part of the object type inspite of the fact that all classes inherit from object type. So that it doesn't make sense here to put argument type of object.

        class Invoker
        {
            public void Method(object instance)
            {
                instance.InstanceMethod();//Not able to resolve the InstanceMethod
            }
        }

Even the generic type doesn't make sens as a solution in this case

        class Invoker<T> where T : class
        {
            public void Method(T instance)
            {
                instance.InstanceMethod();//Not able to resolve the InstanceMethod
            }
        }


The only solution for that is to refactor the code by making all the classes implementing an interface that defines InstanceMethod as the following code illustrates.

        interface IInterface
        {
            void InstanceMethod();
        }
        #region first alternative
        public class FirstClass : IInterface
        {
            public void InstanceMethod()
            {
                Console.WriteLine("The first class is invoked");
            }
        }
        public class SecondClass : IInterface
        {
            public void InstanceMethod()
            {
                Console.WriteLine("The second class is invoked");
            }
        }
        public class ThirdClass : IInterface
        {
            public void InstanceMethod()
            {
                Console.WriteLine("The third class is invoked");
            }
        }

But suppose now that we don't have the code source of those classes?

It won't be possible to refactor the code so that it suits our need.

Using dynamic keyword is a solution key for this case. If we use this bellow code

        class Invoker
        {
            public void Method(dynamic instance)
            {
                instance.InstanceMethod();//Enable to resolve the InstanceMethod :)
            }
        }

Then the problem is resolved as the type determination is reported to the run time then the corresponding method (InstanceMethod) to the given argument (instance) type will be invoked in that moment.

As a conclusion for this section we can say that dynamic programming introduces a new kind of dispatching based not only on the member invoker but also on the dynamic arguments those overload a set of methods.

5.The dynamic keyword vs. the generic type

Suppose now this case

        static void Add<T>(T operand1, T oprand2)
        {
            Console.WriteLine(operand1 + oprand2);
            //This will result a compile time error
        }

Me personaly, I suffred a lot from that issue. But with the dynamic the problem is resolved

        static void Add(dynamic operand1, dynamic operand2)
        {
            Console.WriteLine(operand1 + operand2);
        }

In the other hand, we have to be careful when calling this code. This bellow code for example will throw an exception at run time as there is not an overloaded operator + version that supports the addition between 2 and object.

Add(2, new object());

Hence a RuntimeBinderException will be thrown. Then we can refractor the code to avoid this kind of problems.

        static void Add(dynamic operand1, dynamic operand2)
        {
            try
            {
                Console.WriteLine(operand1 + operand2);
            }
            catch (RuntimeBinderException)
            {
                Console.WriteLine("Unsupported operantion");
            }
        }

As a conclusion for this section, it is possible to avoid some situations where generics illustrates some limits but one has to be careful to avoid application instability as all anomalies are reported to the runtime.

6. The dynamic keyword vs. reflection mechanism

To illustrate the dynamic programming using dynamic keyword over reflection let's suppose this case:

        class DummyClass
        {
            public void Method(int x)
            {
                Console.WriteLine("{0} is an integer", x);
            }
            public void Method(string x)
            {
                Console.WriteLine("{0} is a string", x);
            }
            public void Method(double x)
            {
                Console.WriteLine("{0} is a double", x);
            }
            public void Method(Person x)
            {
                Console.WriteLine("{0} is a person", x);
            }
        }
        class Person
        {
            public string Name { get; set; }
        }

Suppose now that we are in situation to deal with those above methods by retrieving and invoking them through reflection. Then the implementation in that case will be as follow

        static void Main(string[] args)
        {
            object[] arr = { 1, 2.3, "viva lalgery !!!", new Person { Name = "Bechir" } };
            DummyClass instance = new DummyClass();
            Type t = typeof(DummyClass);
            MethodInfo[] methods = t.GetMethods();
            MethodInfo intMethod = methods[0];
            MethodInfo stringMethod = methods[1];
            MethodInfo doubleMethod = methods[2];
            MethodInfo personMethod = methods[3];
            foreach (var item in arr)
            {
                if (item.GetType() == typeof(int))
                {
                    intMethod.Invoke(instance, new object[] { item });
                }
                else if (item.GetType() == typeof(string))
                {
                    stringMethod.Invoke(instance, new object[] { item });
                }
                else if (item.GetType() == typeof(double))
                {
                    doubleMethod.Invoke(instance, new object[] { item });
                }
                else if (item.GetType() == typeof(Person))
                {
                    personMethod.Invoke(instance, new object[] { item });
                }
            }
            Console.Read();
        }

Now, if we try to use the dynamic keyword alternative instead, the code will be dramatically simplfied like this:

            object[] arr = { 1, 2.3, "viva lalgery !!!", new Person { Name = "Bechir" } };
            DummyClass instance = new DummyClass();
            foreach (dynamic item in arr)
            {
                instance.Method(item);
            }
            Console.Read();

The both codes, namely the reflection one and the dynamic one give the same result.

As a conclusion, the dynamic keyword comes to solve some problems that a developer can encounter especially when the static programming mode illustrate some constraints for the developer to implement some concepts.

Good Dotneting!!!


Similar Articles