请考虑以下代码:
class Program {
void Foo<T>() { }
static void Main(string[] args) {
dynamic p = new Program();
p.Foo();
}
}
令人惊讶的是,对p.Foo()的调用无效,因为动态绑定器无法知道要用于T的类型。具体的失败是:
“无法从用法中推断出方法'ConsoleApplication1.Program.Foo()'的类型参数。请尝试明确指定类型参数。”
现在我的问题是:有没有办法指定泛型类型,或者这种方法是不是可以使用'dynamic'来调用?
答案 0 :(得分:14)
正如Jared所说,您可以像在静态调用中一样在代码中指定它:
using System;
class Program {
void Foo<T>() {
Console.WriteLine(typeof(T));
}
static void Main(string[] args) {
dynamic p = new Program();
p.Foo<string>();
}
}
以上代码打印System.String
。
现在如果你只是在执行时知道T
,那就稍微困难了。如果你有一个实例,你可以一起使用动态类型和类型推理:
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;
}
}
编辑:帕维尔在评论中提出了一个惊人的想法。您不需要提出T
的实例,只需要一个数组。这意味着您甚至可以使用类型参数,而您通常无法获取 T
的实例(例如,由于私有构造函数):
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));
}
}
在有人问之前 - 不,这不允许你动态调用Foo<Enumerable>
- 你仍然不能使用静态类作为类型参数,即使你试图将尝试延迟到执行时间:)
如果由于某种原因所有这些都失败了,它会恢复正常反射...获取方法信息,调用MakeGenericMethod
并调用它。
答案 1 :(得分:2)
为什么不完全按照非动态类型
指定类型p.Foo<int>();
答案 2 :(得分:1)
在这种情况下,“p”的类型无关紧要,无论您将其声明为动态还是程序,都会收到此错误。< / p>
错误是无法推断T的类型,因为没有将类型为T的参数传递给该方法,并且该方法不是泛型类的一部分。在这种情况下,编译器无法推断出T是什么类型。
但您应该可以执行以下操作:
class Program {
void Foo<T>() { }
static void Main(string[] args) {
dynamic p = new Program();
p.Foo<int>();
}
}
当你调用Foo时,你只需要明确定义T的类型。
答案 3 :(得分:0)
为什么你不能指定T
是dynamic
?
p.Foo<dynamic>();