Tutorial :Limiting type arguments for generics in C#



Question:

I could very will be imagining things, but I seem to recall in Java that I can declare a field or parameter as such:

public class BarHandler{        public Class<? extends Foo> fooType;        public ProcessedBar Process(string xml){          Foo foo = fooType.GetInstance();          return foo.process(xml)      }  }  

This can be useful for factory style systems where you have to be able to generate new instances of the type in question for example.

I am trying to figure out if there is an analog to this in C#, or if possibly this is just something that is available within Java.


Solution:1

Here's a variation of 280Z28's answer. I've renamed the "Type" class to "Factory", since in my version it exposes a GetInstance method instead of a Value property of type Type. This uses 2 generic parameters and generic constraints to enforce the rules that were in the original answer's constructor for the Type class.

public abstract class Factory<T>  {      public abstract T GetInstance();  }    public sealed class IoCFactory<T, TDerived> : Factory<T>      where TDerived : T // compiler enforces that TDerived derives from T  {      public override T GetInstance()      {          // TODO: retrieve instance of TDerived from IoC container such as Spring.NET, StructureMap, Unity, etc.          throw new NotImplementedException();      }  }    public sealed class ActivatorFactory<T, TDerived> : Factory<T>      where TDerived : T, new() // compiler enforces that TDerived derives from T and that it has a parameterless constructor  {      public override T GetInstance()      {          return Activator.CreateInstance<TDerived>();      }  }    public class BarHandler  {      public Factory<Foo> fooFactory { get; set; }        public ProcessedBar Process(string xml)      {          Foo foo = fooFactory.GetInstance();          return foo.Process(xml);      }  }    class Program  {      static void Main(string[] args)      {          BarHandler handler = new BarHandler();            handler.fooFactory = new ActivatorFactory<Foo, Bar>();            var processedResult = handler.Process("<bar>Yar!</bar>");      }  }  


Solution:2

Yes, see generic constraints. The equivalent to your example would be:

public class SomeClass<T>      where T : Foo  {      private T fooType;  }  

EDIT AFTER YOUR EDIT: I believe you're referring to wildcards, in which case you should read about covariance and contravariance with respect to generics.


Solution:3

public class GenericClass<T> where T : Foo  


Solution:4

You could use a very simple wrapper for this annotation and a cheap runtime check:

public sealed class Type<T>  {      public Type(Type type)      {          if (type == null)              throw new ArgumentNullException("type");          if (!typeof(T).IsAssignableFrom(type))              throw new ArgumentException(string.Format("The specified type must be assignable to '{0}'.", typeof(T).FullName));            this.Value = type;      }        public Type Value      {          get;          private set;      }  }  

Use Activator.CreateInstance to actually create an instance of the type. Suppose FooDerived is derived from Foo.

Type<Foo> fooType = new Type<Foo>(typeof(FooDerived));  Activator.CreateInstance(fooType.Value);  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »