C# 如何执行运行时泛型
本文关键字:运行时 泛型 执行 何执行 | 更新日期: 2023-09-27 18:36:11
Java让我恼火的一件事是泛型类型参数的编译时翻译的糟糕实现。
我可以观察并理解 C# 实现要好得多,但我对它的工作原理感到困惑。
本质上,你怎么能说:
T t = new T()
如果您不知道 T 的类型,因此不知道构造函数参数要求?
我可以看到
Class<T> cl = T.class
或
T[] tarr = new T[0]
但是如果您不知道构造T的要求,我不明白如何真正创建一个新的T实例?
只有当 T 被限制为具有一个普通的、无参数的公共构造函数时,您才能执行new T();
,例如:
public class Foo<T> where T : new() {
private myT = new T();
}
此外,无法指定存在任何其他类型的构造函数。 这是不可能的:
// Doesn't work
public class Foo<T> where T : new(String, Int) {
private myT = new T("Foo", 5);
}
对于您的其他要点,这就是您在运行时获取 T 类型的方式:
var tType = typeof(T);
创建 T
数组实际上不会创建任何实例(除非T
是值类型,在这种情况下,它会创建该类型的默认值):
// Space for 32 T's, but nothing in the array.
// If T is a value type, like an int for instance,
// each one would have the default value (0 for int, for example)
var arrayOfT = new T[32];
除非使用 where T : new()
约束将泛型类型约束为具有无参数构造函数,否则不能说new T()
— 请参阅类型参数的约束。
并且没有"构造函数参数要求",因为唯一支持的构造函数是无参数构造函数。例如,您不能使用new T(false)
— 不允许使用形式where T : new(bool)
的约束。
您要求编译器强制T
使用无参数构造函数,以便他知道您可以new T()
。例如:
class Test<T>
{
T Create()
{
return new T();
}
}
它不会编译,因为编译器无法确定T
不会是抽象类,并且它是否具有默认构造函数。要使其正常工作,您必须在 T 的实际类型上添加约束:
class Test<T> where T : new()
现在编译器将强制T
成为具有默认构造函数的非抽象类。例如,此代码无效,因为给定的类型是抽象的:
abstract class AnotherTest
{
public void Test()
{
Test<Derived> test = new Test<Derived>();
}
}
同样,如果您尝试使用没有默认构造函数的类,编译器将发出错误:
class AnotherTest
{
public AnotherTest(string someParameter)
{
}
public void Test()
{
Test<Derived> test = new Test<Derived>();
}
}
对于数组,它有点不同。实际上,您只需要求编译器为给定数量的插槽保留内存,而无需为该对象分配内存(在引用类型的情况下,它只会在每个插槽中放置null
)。
MSDN
上的参考
- 泛型简介
- 泛型类型约束
new
约束
new T()
只是Activator.CreateInstance<T>()
的语法糖