【发布时间】:2017-01-19 12:37:30
【问题描述】:
在下面显示的示例代码中,“CompileError”方法不会编译,因为它需要where T : new() 约束,如CreateWithNew() 方法所示。但是,CreateWithActivator<T>() 方法编译得很好,没有约束。
public class GenericTests
{
public T CompileError<T>() // compile error CS0304
{
return new T();
}
public T CreateWithNew<T>() where T : new() // builds ok
{
return new T();
}
public T CreateWithActivator<T>() // builds ok
{
return Activator.CreateInstance<T>();
}
}
这是为什么?
根据引用MSDN documentation 和this question 的https://stackoverflow.com/a/1649108/531971,泛型中的new T() 表达式实际上实现 使用Activator.CreateInstance<T>()。所以我不明白为什么调用new T() 需要以使用Activator.CreateInstance<T>() 时可以省略的方式约束泛型类型。
或者,反过来说:where T : new() 约束的意义是什么,如果通过直接使用完全相同的底层基础设施,在没有约束的通用方法中创建 T 的实例很容易?
【问题讨论】:
-
因为
CreateInstance()只使用普通的旧反射并且不受任何约束。如果该类型有一个默认构造函数,它将创建它。 -
这是自我控制的事情。您可以通过反射完成几乎所有事情(甚至破坏所有 OOP 原则),但许多人不会欣赏它,因为它很脏。
-
有很多方法可以编写笨拙的代码,让您消除编译时错误并生成运行时错误。这只是一个例子。例如。
dynamic允许您编写对不存在的函数的调用,因此您得到的不是编译器错误,而是运行时异常。同样,在这里,CreateInstance让您推迟发现不存在无参数构造函数,直到运行时。 -
问题“where T : new() 约束有什么意义”可以提炼为“类型约束有什么意义?”他们都有相同的答案。
标签: c# .net generics activator type-constraints