(+N) Consulting Inc.

Consulting. Software solutions. Training.

C# Generics - Interface declaration

I was challenged recently with a question about generics with constraints. The claim was that it's only a compile flaw that allows your to declare an interface for a generic type with a constraint. Namely that the syntax public interface ISomething <T> where T: SomeClass would pass compilation but would not be useful (runtime) because you can't declare a variable ISomething myVar = new ISomething<SomeClass>(); or something to that extent. I went home feeling a bit uneasy about the discussion, then coded this up the way I see it. While it is completely true that you can't 'new' an interface, using an interface that has a generic type is completely possible and legal. Here it is in all it's g(l)ory. using System; using System.IO; using System.Text; /// Demo of generic interface declaration with constraint. /// Showing compilation and runtime feasibility. namespace NH.Demo { class Demo { static void Main(string[] args) { ITryInstance o1 = new GenericInstanceA(); ITry<MyDerivedType> o2 = new GenericInstanceB(); Console.WriteLine("Generic instance 1 " + o1.ProperT.SomeField); Console.WriteLine("Generic instance 2 " + o2.ProperT.SomeField); } } interface ITry<T> where T : MyBaseType { T ProperT{ get; } } public class MyBaseType { public string SomeField; } public class MyDerivedType : MyBaseType { public MyDerivedType(string arg) { base.SomeField = arg; } } interface ITryInstance : ITry<MyDerivedType> { } /// <summary> /// this will fail. cosntraint violation /// "The type 'string' must be convertible /// to 'NH.Demo.MyBaseType' in order to use it as /// parameter 'T' in the generic type or /// method 'NH.Demo.ITry<T>'" /// </summary> //interface IFail : ITry<string> { } public class GenericInstanceA : ITryInstance { MyDerivedType ITry<MyDerivedType>.ProperT { get { return new MyDerivedType("hi there!"); } } } public class GenericInstanceB : ITry<MyDerivedType> { MyDerivedType ITry<MyDerivedType>.ProperT { get { return new MyDerivedType("hi there! again"); } } } }