Is there any way to set the type parameter?

Is it possible to use a type parameter as an implementation of a specific interface in Runtime without Reflection? The following pseudo code is what I want to do.

void Run1<T> () { // ... if (typeof (IEnumerable).IsAssignableFrom (typeof (T)) { Run2<T implementing IEnumerable> (); // <- use T as implementing IEnumerable } // ... } void Run2<T> () where T : IEnumerable { // ... } 
+7
c #
source share
2 answers

No, I do not believe that you can do it simply.

If you control all the code, you can have a public version of Run2 with a restriction, but a private implementation of Run2 without a restriction that you call from Run1 :

 public void Run1<T>() { // ... if (typeof(IEnumerable).IsAssignableFrom(typeof(T)) { Run2Impl<T>(); } // ... } public void Run2<T>() where T : IEnumerable { Run2Impl<T>(); } private void Run2Impl<T>() { // Need to cast any values of T to IEnumerable here } 
+4
source share

If you must abandon the need not to use reflection, you can do this using a small detour.

 public class Tester { private static readonly MethodInfo _run2Method = typeof(Tester).GetMethod("Run2"); public void Run1<T>() { if (typeof(IEnumerable).IsAssignableFrom(typeof(T))) Run2AsIEnumerable<T>(); else Console.WriteLine("Run1 for {0}", typeof(T)); } public void Run2<T>() where T : IEnumerable { Console.WriteLine("Run2 for {0}", typeof(T)); } private void Run2AsIEnumerable<T>() { Console.WriteLine("Detour to run2 for {0}", typeof(T)); var method = _run2Method.MakeGenericMethod(typeof(T)); method.Invoke(this, new object[0]); } } 

Note that this can be done more efficiently by creating and caching delegates for specific types on demand.

The result of this:

 new Tester().Run1<IEnumerable<int>>(); 

is an:

 Detour to run2 for System.Collections.Generic.IEnumerable`1[System.Int32] Run2 for System.Collections.Generic.IEnumerable`1[System.Int32] 
+1
source share

All Articles