Type Systems Demystified
Written by Nikos Vaggalis   
Friday, 19 February 2010
Article Index
Type Systems Demystified
Late binding
Perl
C# and Reflection
Dynamic typing
Automation and delegates

C# and Reflection

In essence reflection is used when you have an assembly with no compile time information on it and you must load it at runtime. By using Reflection you can then interrogate it from your code dynamically and get all the type info from within. This also forms the basis of plug-and-play Component architecture where you do interface based programming by separating interface from implementation.

Back to our example we said that in VB.net using "strict off" enables late-binding. In C# there is no such directive so we have to use the Reflextion API for the same purpose.

Example 5

 class Class1
{
public int MyMethod(int x, int b)
{
return x + b;
}
}
   class Program
{
static void Main(string[] args)
{
object myobj;
myobj = new Class1();
       Type T = myobj.GetType();
       object[] param = new object[2];
param[0] = 1;
param[1] = 2;
       int myresult = 
(int)T.InvokeMember(
"MyMethod",
BindingFlags.InvokeMethod |
BindingFlags.Public |
BindingFlags.Instance,
null, myobj, param);
       Console.WriteLine(
myresult.ToString());
//prints : 3
     }
}

I'm not going to get into details but this example is the equivalent of the example in VB.net with strict off. It requires more lines of code and at the same time proves a bit cumbersome. But this is going to be changed by the introduction of a new type called dynamic, which adds dynamic language capabilities to C#.

Dynamic type

The code inside the Main method of the above example in Reflection could be replaced by using the new Dynamic type and become as small as:

 dynamic myobj = new Class1();
int myresult = myobj.MyMethod(1,2);

Example 5a

 using System;
 namespace ConsoleApplication4
{
class Class1
{
public int MyMethod(int x, int b)
{
return x + b;
}
}
   class Program
{
static void Main(string[] args)
{
dynamic myobj = new Class1();
int myresult = myobj.MyMethod(
1, 2);
       Console.WriteLine(
myresult.ToString());
//prints : 3
}
}
}

Again, it does not do compile time checking. If something goes wrong it will be dicovered at runtime
This will allow you to write code for easier interop with COM objects and .NET Assemblies, or even in cases where the type is generated at runtime by a call to a method like :

 dynamic d = MakeDynamicType();
 d.MyMethod();

Single versus multiple method dispatch

One marvellous use of the dynamic type is that it allows for runtime method overloading or multiple method dispatch, an advanced polymorphic concept.

In common with most OOP languages C# and VB.net are single dispatch languages and resolve method overloading at compile time. This means that the method chosen is based on the compile time type and the type of the method parameters.

Example 6

  class Fruit
  {

  }

  class Apple : Fruit
  {

  }

  class Class1
  {
       public virtual int Method1(Fruit a)
       {
               return 1;
       }

       public virtual int Method1(Apple a)
       {
               return 2;
       }

       public virtual int Method1(int x)
       {
               return 3;
       }
  }

  class Class2 : Class1
  {
       public override int Method1(Fruit a)
        {
               return 4;
        }

        public override int Method1(Apple a)
        {

               return 5;
        }

        public override int Method1(int x)
        {
               return 6;
        }

  }

 

  class Program
  {
         static void Main(string[] args)
         {
               Fruit objF = new Apple();
               Class1 objA = new Class2();

                int x = objA.Method1(objF);
                Console.WriteLine(x.ToString());
                 //prints : 4
         }

  }

The method resolution works like this - objA's compile type is Class1 but runtime type is Class2. To resolve the binding the compile time type is used, that is Class1. Thus a method with name Method1 and argument of type Fruit is looked for. This is public virtual int Method1(Fruit a). Since it is virtual the runtime type is consulted which resolves to Class2' public override int Method1(Fruit a).

Although the method is 'virtual' and the runtime type is consulted for looking up the method, it comes a bit too late since the signature of the method is determined at compile time.

The same result would also be achieved with late binding/option strict off. In this case although the compile time type information would be totally disregarded and the method look up would be done at runtime, it would also use the compile time parameter type for identifying the method.

So at runtime the object's type is Class2 but the argument passed to the method is of compile type Fruit, thus Class2's public override int Method1(Fruit a) is chosen, again.

What multiple method dispatch would do differently is that it would choose the method based on the runtime type of the parameter.That is, it would have chosen Class2 public override int Method1(Apple a)
since the method call objA.Method1(objF) uses an objF whose runtime type is of Apple type.
The following example demonstrates the concept.

Example 7

  class Fruit
{
  }
  class Apple : Fruit
{
  }
  class Class1
{
public virtual int Method1(
Fruit a)
{
return 1;
}
      public virtual int Method1(
Apple a)
{
return 2;
}
      public virtual int Method1(int x)
{
return 3;
}
}
  class Class2 : Class1
{
public override int Method1(
Fruit a)
{
return 4;
}
      public override int Method1(
Apple a)
{
return 5;
}
      public override int Method1(int x)
{
return 6;
}
  }
  class Program
{
static void Main(string[] args)
{
Fruit objF = new Apple();
dynamic objF1 = new Apple();
           Class1 objA = new Class2();
           int x = objA.Method1(objF);
Console.WriteLine(
x.ToString());
//prints : 4
int y = objA.Method1(objF1);
Console.WriteLine(
y.ToString());
//prints : 5
           //object objB = new Apple();
//int z = objA.Method1(objB);
//Console.WriteLine(
z.ToString());
      }

Just to see the difference between Object and Dynamic uncomment the following lines

 //object objB = new Apple();
//int z = objA.Method1(objB);
//Console.WriteLine(z.ToString());

and run the example again. You get the following compile time errors:

Error 1 The best overloaded method 
match for
'ConsoleApplication6.Class1.Method1(
ConsoleApplication6.Fruit)' has some
invalid arguments
Error 2	Argument 1: cannot convert from 
'object' to 'ConsoleApplication6.Fruit'

This proves that Object is treated differently by Dynamic - the Object type is used for compile time method resolution, whereas Dynamic is used for runtime method resolution

This advanced polymorphic concept was formerly supported only by Reflection but now will be supported by the Dynamic type in the .NET environment, and in the forthcoming Perl6 by using 'multi' subroutines.

Of course since Perl has no compile time type safety it could not have method overloading at compile time. Were method overloading in Perl to exist it would be a runtime affair by definition. Of course for it to work the methods or subs would require typed parameters which do not exist in earlier Perl versions and thus to employ MMD you had to resort to big IF..Then clauses. But now the Perl6 type system will allow for this sort of functionality.

<ASIN:1590594525>

<ASIN:1565922204>

<ASIN:1430225297>



Last Updated ( Friday, 09 November 2012 )