[英]How does C# do runtime generics?
让我烦恼的是Java的糟糕实现,泛型类型实参的编译时转换。
我可以观察并理解C#实现要好得多,但是我对它的工作方式感到困惑。
本质上,您怎么说:
T t = new T()
如果您不知道T的类型,因此不知道构造函数的参数要求?
我可以看到
Class<T> cl = T.class
要么
T[] tarr = new T[0]
但是,如果您不知道构造T的要求,那么我看不到如何真正创建T的新实例?
您只能执行new T();
如果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];
实际上,您要求编译器强制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上的参考
除非使用where T : new()
约束将通用类型约束为具有无参数的构造函数,否则您不能说new T()
-请参阅“类型参数的约束” 。
而且没有“构造函数参数要求”,因为唯一支持的构造函数是无参数构造函数。 例如,您不能使用new T(false)
-不允许where T : new(bool)
的形式的约束where T : new(bool)
。
new T()
仅仅是Activator.CreateInstance<T>()
的语法糖
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.