Can general parameters be set when using dynamic variables?

Consider the following code:

class Program { void Foo<T>() { } static void Main(string[] args) { dynamic p = new Program(); p.Foo(); } } 

Note that the call to p.Foo () is invalid because the dynamic binder has no way of knowing which type to use for T. Specific failure:

"Type arguments for the method" ConsoleApplication1.Program.Foo () "cannot be taken out of use. Try explicitly specifying type arguments.

Now my question is: is there a way to specify a generic type, or can this method simply not be called using "dynamic"?

+4
source share
4 answers

As Jared says, you can specify it in the code as you would for a static call:

 using System; class Program { void Foo<T>() { Console.WriteLine(typeof(T)); } static void Main(string[] args) { dynamic p = new Program(); p.Foo<string>(); } } 

The above code prints System.String .

Now, if you only know T at runtime, it's a little more complicated. If you have an instance, you can use dynamic typing and the output type together:

 using System; class Program { void Foo<T>() { Console.WriteLine(typeof(T)); } static void Main(string[] args) { dynamic p = new Program(); dynamic v = GetRandomInstance(); // Now to call p.Foo<T> where T is the type of v value... Dummy(v, p); } static void Dummy<T>(T t, Program p) { p.Foo<T>(); } static object GetRandomInstance() { return DateTime.Now.Hour > 10 ? "hello" : (object) 10; } } 

EDIT: Paul came up with a great idea in the comments. You do not need to invent an instance of T , just an array. This means that you can even use type arguments in which you normally could not get an instance of T (for example, due to a private constructor):

 using System; class PrivateConstructor { private PrivateConstructor() {} } class Program { static void Foo<T>() { Console.WriteLine(typeof(T)); } static void CallFooProxy<T>(T[] array) { Foo<T>(); } static void CallFoo(Type t) { dynamic array = Array.CreateInstance(t, 0); CallFooProxy(array); } static void Main(string[] args) { CallFoo(typeof(PrivateConstructor)); } } 

Before anyone asks - no, this does not allow you to dynamically call Foo<Enumerable> - you still cannot use a static class as an argument of type, even if you try to postpone the attempt until runtime :)

If all this fails for some reason, it returns to reflection as usual ... get information about the method, call MakeGenericMethod and call it.

+14
source

Why not specify the type in the same way as for the non-dynamic type

 p.Foo<int>(); 
+2
source

In this case, it does not matter what type of "p", whether you declare it as dynamic or as a Program , you will get this error.

The error indicates that the type T cannot be inferred because the parameters of the method T are not passed to the method, and this method is not part of the universal class. In this case, the compiler cannot determine which type of T.

You should be able to do the following:

 class Program { void Foo<T>() { } static void Main(string[] args) { dynamic p = new Program(); p.Foo<int>(); } } 

You just need to explicitly specify type T when you call Foo.

+1
source

Why couldn't you indicate that T is dynamic ?

 p.Foo<dynamic>(); 
0
source

All Articles