Generics and constraints

1. How to make possible compiling code which doesn’t have only System.Object types?

2. What do generic constraints mean?

3. What are the limitations of generics constraints?

4. Which virtual methods the C# compiler allows to override?

Example 1:

        private bool Compare<T>(T param1, T param2)

        {

            return param1.Equals(param2);

        }

 

The C# allows compiling this code because types are derived from System.Object.

Example 2:

        //’T’ does not contain a definition for ‘CompareTo’ and no extension method ‘CompareTo’

        //accepting a first argument of type ‘T’ could be found (are you missing a using directive

        //or an assembly reference?)

        private int CompareTo<T>(T param1, T param2)

        {

            return param1.CompareTo(param2);

        }

Example 3:

        private int CompareTo<T>(T param1, T param2) where T  : IComparable<T>

        {

            return param1.CompareTo(param2);

        }

To make possible compiling this code we can use generics constraints mechanism.  

A generic constraint is a way to limit number of types that can be specified for a generic argument.

Generics constraints can be applied to a generic’s type’s type parameter as well as methods to a generics method’s type parameters.

Example 4:

    //It’s possible to define types

    internal class Foo { };

    internal class Foo<T> { };

    internal class Foo<T, M> { };

 

    //The namespace ‘Constraints’ already contains a definition for ‘Foo’

    internal class Foo<T> where T : ICloneable { }

 

    //The namespace ‘Constraints’ already contains a definition for ‘Foo’

    //Partial declarations of ‘Constraints.Foo<T,M>’ must have the same type parameter names in the

    //same order   

    internal class Foo<T1, M1> { }

 

    internal class Bar

    {

        private void Method(){}

        private void Method<T>() { }

        private void Method<T, M>() { }

 

        //Type ‘Constraints.Bar’ already defines a member called ‘Method’ with the same parameter types

        private void Method<T>() where T : IAsyncResult { }

 

        //Type ‘Constraints.Bar’ already defines a member called ‘Method’ with the same parameter types

        private void Method<T1, M1>(){ }

    }

The CLR doesn’t allow generics constraints and types name overloading for types and overriding for methods.

Example 5:

    internal class Base1

    {

        protected virtual void M1<T1, T2>(){}

    }

 

    internal class Derived1 : Base1

    {

        //’Constraints.Derived1.M1<T1>()’: no suitable method found to override

        protected override void M1<T1>() { }

 

        //This method will be compiled

        protected override void M1<T3, T4>() { }

    }

 

    internal class Base2

    {

        protected virtual void M1<T1, T2>() where T1 : class where T2 : T1

        {

 

        }

    }

 

    internal class Derived2 : Base2

    {

        //Constraints for override and explicit interface implementation methods are inherited

        //from the base method, so they cannot be specified directly

        protected override void M1<T3, T4>() where T3 : class where T4 : T3{ }

    }

The CLR allow overriding virtual generics methods if only they have the same number of type parameters and do not redefine generics constraints. However it is possible to override generics virtual methods even if they have different type parameters.  

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