Consider the following code:
class Program {
void Foo<T>() { }
static void Main(string[] args) {
dynamic p = new Program();
p.Foo();
}
}
Note surprisingly, the call to p.Foo() is not valid because the dynamic binder has no way of knowing what type to use for T. The specific failure is:
" The type arguments for method 'ConsoleApplication1.Program.Foo()' cannot be inferred from the usage. Try specifying the type arguments explicitly. "
Now my question is: is there a way to specify the generic type, or is such method simply not callable using 'dynamic'?
As Jared says, you can specify it in code just 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 execution time, it's slightly harder. If you have an instance of it though, you could use dynamic typing and type inference 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's 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: Pavel came up with an amazing idea in the comments. You don't need to come up with an instance of T
, just an array. This means you can even use type arguments where you wouldn't normally be able to get an instance of T
(eg 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 doesn't let you call Foo<Enumerable>
dynamically - you still can't use a static class as a type argument, even if you try to delay the attempt until execution time :)
If all of that fails for some reason, it's back to reflection as normal... get the method info, call MakeGenericMethod
and invoke it.
为什么不像非动态类型那样完全指定类型
p.Foo<int>();
In this case, it doesn't matter what type "p" is, whether you declare it as dynamic or as Program , you will receive this error.
The error is saying that the type of T cannot be inferred because there are no parameters of type T being passed to the method, and the method isn't part of a generic class. In this case, there's no way for the compiler to infer what type T is.
You should be able to do the following, though:
class Program {
void Foo<T>() { }
static void Main(string[] args) {
dynamic p = new Program();
p.Foo<int>();
}
}
You just need to explicitly define the type of T when you call Foo.
为什么你不能指定T
是dynamic
?
p.Foo<dynamic>();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.