Generics and interface constraints

  1. Compile – time safety.
  2. Much less boxing. What does the C# compiler emits when generic interface constraints are defined?

Example 1:

    class GenericInterfaceConstraitTest

    {

        public static int Compare<T>(T first, T second) where T : IComparable, IConvertible

        {

            return first.CompareTo(second);

        }

    }

    class Program

    {

static void Main(string[] args)

{

//There is no boxing conversion from ‘System.Guid’ to ‘System.IConvertible’.    

Console.WriteLine(GenericInterfaceConstraitTest.Compare(Guid.NewGuid(), Guid.NewGuid()));       

}

    }

As we can see from the example above the method can take only parameters which implements both interfaces as defined in the method. This method can take parameters which are derived from the base class, that implements  both interfaces as well. So generic type constraints provide compile – type safety.

Example 2.1:

        public static int Compare(IComparable first, IComparable second)

        {

            return first.CompareTo(second);

        }

.method public hidebysig static int32 Compare(class [mscorlib]System.IComparable first, class [mscorlib]System.IComparable second) cil managed
{
    .maxstack 2
    .locals init (
        [0] int32 CS$1$0000)
    L_0000: nop
    L_0001: ldarg.0
    L_0002: ldarg.1
    L_0003: callvirt instance int32 [mscorlib]System.IComparable::CompareTo(object)
    L_0008: stloc.0
    L_0009: br.s L_000b
    L_000b: ldloc.0
    L_000c: ret
}
 

Example 2.2:

        public static int Compare<T>(T first, T second) where T : IComparable, IConvertible

        {

            return first.CompareTo(second);

        }

 

.method public hidebysig static int32 Compare<([mscorlib]System.IComparable) ([mscorlib]System.IConvertible) T>(!!T first, !!T second) cil managed
{
    .maxstack 2
    .locals init (
        [0]int32 CS$1$0000)
    L_0000: nop
    L_0001: ldarga.s first
    L_0003: ldarg.1
    L_0004: box !!T
    L_0009: constrained !!T
    L_000f: callvirt instance int32 [mscorlib]System.IComparable::CompareTo(object)
    L_0014: stloc.0
    L_0015: br.s L_0017
    L_0017: ldloc.0
    L_0018: ret
}
 

As we can see from the example 2.2 the C# compiler emits special IL instructions for the generic type parameter which allows us to avoid boxing.

}

}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s