Dynamic C#
Written by Mike James   
Tuesday, 11 March 2014
Article Index
Dynamic C#
Anonymous types
Dynamic typing
Beyond .NET objects

Dynamic typing

The other end of the spectrum from or static typing is dynamic typing. In true dynamic typing a variable really can change its type at runtime.

This this doesn't have to be the abandonment of type checking just a move to type checking at run rather than compile time. C# hasn't quite adopted the "duck typing" approach that makes languages such as JavaScript, Ruby and Python, as it is still attempting to play within the strong typing rules it started out with.

 

Banner

 

The best way of thinking about dynamic type is as a sort of formal way to use a general object type which which allows you access to the methods and properties of the actual data type in use without the need to cast.

For example, suppose we have a class:

public class MyClass {
 public int MyProperty;
 public int MyMethod() {
  return 1;
 }
}

If we now create an instance using an object reference type:

object MyObject = new MyClass();

then trying to access any of the methods or properties of the object will fail for obvious reasons – an object type doesn’t have the methods and properties of a MyClass type.

However, if you use a cast to MyClass then you can access all of the properties and methods as if MyObject was of type MyClass that is:

((MyClass) MyObject).MyMethod();

works perfectly.

In this sense using object and cast has long been the C# programmer’s way of implementing dynamic typing. In this sense dynamic typing is nothing new to the language.

However you must have had the thought

“why do I need to cast the object to the correct type – either the method call works or doesn’t work at run-time”. 

Apart from making it easier to discover the programmer’s intention the cast does absolutely nothing to protect you from an error at compile time – any problems only become apparent at runtime.

With the new dynamic type you can indeed “drop the cast”.

The same code in C# can be written using the dynamic type introduced in version 4.0:

dynamic MyObject = new MyClass();
MyObject.MyMethod();

The dynamic type only resolves to a method or property at runtime.

 

csharp

 

Interestingly you can mix dynamic and anonymous as in:

dynamic MyObject = new MyClass();
var i=MyObject.MyMethod();

and the compiler correctly works out that i should be an int – suggesting that it isn’t completely blind to the type stored in MyObject. Notice that as dynamic is a valid static type name it is perfectly possible that an anonymous type will resolve to dynamic.

You can swap from dynamic to fully static simply by making appropriate assignments. For example:

dynamic j = 1;
int i = j;

first creates a dynamic variable, an int, which is then converted to a strongly typed int. You can also force a conversion using a cast but, as always, if it can’t be done the result is a runtime exception.

Notice that dynamic really is dynamic in the sense that the determination of its type at runtime isn't a one off. A dynamic type can change its type as many times as necessary. For example:

dynamic i;
i = 1;
i = i + 1;
i = "mike";
i = i + 1;

When the int 1 is assigned to it i becomes an int, and i+1 is an integer expression which evaluates to 2. Assigning the string "mike" to i changes its runtime type to string and now i+1 concatenates the string "1" which is implicitly cast from an int to give "mike1".

Notice that there is nothing new going on here as every thing works just as it would if the variable i was first declared as an int and then declared as a string - of course you can't change the type of a static type at compile time.

The guiding principle that has been used in implementing the dynamic type is that what happens should correspond to what happens if the dynamic type was known at compile rather than runtime.

So to work out how a dynamic type behaves simply imagine that you know its type at compile time and what happens in this case should be what happens to the dynamic type.

Late or early?

Whenever you change something in a language, no matter how small or innocent the change is, the ripples spread out and reach parts of the language that you might never have guessed at.

For example, with dynamic typing late binding is the rule even if the method in use isn’t virtual. Consider the following class with two overloaded versions of the same method:

public class MyClass {
 public string MyMethod(int i){
  return "Integer";
 }
 public string MyMethod(double f){
  return "Double"; }
 }

If we now call the method but with a random type, i.e. a the type of the object is selected randomly, something that was impossible to do before the introduction of dynamic, as in:

Random R = new Random();
MyClass MyObject = new MyClass();
dynamic i;
if(R.NextDouble()<.5){
 i = 1;
}else{
 i=1.0;
}
string result=MyObject.MyMethod(i);

then which MyMethod is actually called is determined at run time according to the type of i which is discovered using reflection. If i is a double then MyMethod(double f) is called and if it i is an int then MyMethod(int i) is called.

This should be the behaviour you expect from your understanding of the way that dynamic types work but notice that this means that the late binding is being used in a situation where you might have expected the usual early binding. That is, it fits into the principle that what should happen should be the same as if the type of the dynamic variable was known at compile time.

Overloading And Overriding

This can be slightly more complicated in that we can mix method overloading with overriding in a derived class - but the guiding principle still applies.

For example, suppose we have a derived class which overrides a non-virtual  method in the original MyClass:

public class MyClass2:MyClass{
 public new string MyMethod(double f){
  return "Class2 Double";
 }
}

As the method isn't virtual you would expect early binding to be used i.e. based on the compile type type of the object. However we have already noted that using a dynamic parameter forces late binding. So which is it? 

That is of we now change the creation of MyObject in the previous example to read:

MyClass MyObject = new MyClass2();

which method will be used for a double MyClass's or MyClass2's?

At compile time the type of MyObject is MyClass even if at run time it actually refers to a MyClass2 object and so by the usual early binding rules it should be MyClass's methods that are used and indeed this is what happens - even though which MyClass method is called isn't determined until runtime.

Thus the method call is early bound to the class type but late bound according to the signature of the call.

However,  if you change the method declarations to virtual and override late binding is used on them both and MyClass2's double method is called

This is ruthlessly logical and if you stop to think about it what really should happen in each case.

 

Banner

<ASIN:073568183X>

<ASIN:1449380344>

<ASIN:0735667454>

<ASIN:0133440575>

<ASIN:1449320414>



Last Updated ( Tuesday, 11 March 2014 )
 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.