Mar 122010
 

I have always believed that strong typing is the holy grail of .NET, which is not to be messed with, and it has been my primary grouse with VB.NET is that it uses sneaky workarounds to circumvent the typing rules of the CLR. C# for most of its initial existence followed static typing religiously with slight changes being seen in 3.0 with the var keyword. But in 4.0, everything changed with the introduction of the Dynamic Language Runtime (DLR).

The DLR according to wikipedia is “an ongoing effort to bring a set of services that run on top of the Common Language Runtime (CLR) and provides language services for several different dynamic languages.” As the definition says, it is independent of the CLR and adds no new OpCodes to the IL. Languages like C# used the DLR to introduce dynamic typing while maintaining the existing mechanism of statically determining types.

The dynamic keyword is the C# construct introduced for this. In short – it tells the compiler that the call to this method is to be resolved at runtime and not to be bothered by throwing compiler errors. Lets see a simple example for the usage of the dynamic keyword. Suppose you have a book class which has four main properties – Author, Publisher, Price and Number Of Pages. However, each book may have a lot of other properties as well, which you wont know at design time. So the question arises, how to store the additional information? The first answer that would come to mind is storing them in a collection class and later retrieving it. The dynamic class provides you with a neat way of doing this shown in the code below :-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class Program
    {
        static void Main(string[] args)
        {
            // The dynamic keyword bypasses any compile time checking for this object
            dynamic _daVinciCode = new Book("Sample Author", "SomePublisher", 250, 450);
 
            /*** EXTRA PROPERTIES - NOT PRESENT IN THE OBJECT***/
            _daVinciCode.BookStores = new string[] { "Landmark", "Oddyssey", "Crosswords" };
            _daVinciCode.CitiesAvailable = new string[] { "Delhi", "Bangalore", "Chennai" };
            _daVinciCode.ExtraVat = 45;
 
            /*** PRINTING OUT EXTRA PROPERTIES VALUE ***/
            Console.WriteLine(_daVinciCode.ExtraVat);
        }
 
    }
 
    /// <summary>
    /// This is our dynamic class. It defines 4 concrete properties
    /// and a dictionary class for storing any other property values
    /// as well. The abstract class DynamicObject is implemented
    /// </summary>
    public class Book:DynamicObject
    {
        //Our four defined properties
        public string Author { get; private set; }
        public string Publisher { get; private set; }
        public double Price { get; private set; }
        public int NumberOfPages { get; private set; }
 
        //Constructor - Parametrized
        public Book(string _author, string _publisher, double _price, int _numberOfPages)
        {
            this.Author = _author;
            this.Publisher = _publisher;
            this.Price = _price;
            this.NumberOfPages = _numberOfPages;
        }
 
        //This collection object stores all the extra properties
        public Dictionary<string, object> _extraProperties = new Dictionary<string, object>();
 
        //At runtime this method is called in order to bind the propertyname to a Getter
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            return _extraProperties.TryGetValue(binder.Name.ToLower(), out result);
        }
 
        //At runtime this method is called in order to bind the propertyname to a setter
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            _extraProperties.Add(binder.Name.ToLower(), value);
            return true;
        }
    }

The Book class is a dynamic type and derives from the abstract class DynamicObject. This base class can help determine how binding should occur at runtime. In our example, the dictionary object stores all the additional properties of the book class. The two overriden methods TryGetMember and the TrySetMember are responsible for the binding of the new properties to the dictionary object. The first time a property on a dynamic type is encountered, the DLR binds the property and then caches its address. So any subsequent calls are faster.

More on the DLR in future posts.