【问题标题】:More trivia than really important: Why no new() constraint on Activator.CreateInstance<T>()?琐事多于真正重要:为什么 Activator.CreateInstance<T>() 上没有 new() 约束?
【发布时间】:2011-03-03 23:19:56
【问题描述】:

我想也许有人能回答这个问题,这是一个出于好奇的问题:

.NET v2 中引入的来自System.Activator 的泛型CreateInstance 方法对泛型参数没有类型限制,但需要激活类型的默认构造函数,否则会抛出MissingMethodException。对我来说,这个方法似乎很明显应该有一个类型约束,比如

Activator.CreateInstance<T>() where T : new() {
   ...
}

只是一个遗漏或一些轶事潜伏在这里?

更新

正如所指出的,编译器不允许你写

private T Create<T>() where T : struct, new()
error CS0451: The 'new()' constraint cannot be used with the 'struct' constraint

但是,请参阅 cmets,结构可以用作指定 new() 约束的泛型方法的类型参数。在这种情况下,给定的答案似乎是不限制方法的唯一正当理由......

感谢您查看此内容!

【问题讨论】:

  • +1 非常有趣的问题。我想不出它不应该在那里的原因,所以我也很想知道为什么!
  • 关于你的更新,因为它是多余的;所有值类型都有一个默认构造函数,它将所有值初始化为默认值(这是你调用default(T)时得到的。
  • 所有结构在 C# 中都有默认的 ctors。
  • 澄清一下,鉴于void Foo&lt;T&gt;() where T:new() {}、Foo&lt;DateTime&gt;(); 或Foo&lt;int&gt;(); 都是编译器不会抱怨的完全有效的调用。
  • 很好的问题。我很困惑。 new 约束似乎是与泛型同时引入的,因此它不像是向后兼容问题。也许他们只是忘记了?

标签: c# .net clr c#-2.0 base-class-library


【解决方案1】:

我可能是错的,但我认为它的主要好处是它允许你做这样的事情:

// Simple illustration only, not claiming this is awesome code!
class Cache<T>
{
    private T _instance;

    public T Get()
    {
        if (_instance == null)
        {
            _instance = Create();
        }

        return _instance;
    }

    protected virtual T Create()
    {
        return Activator.CreateInstance<T>();
    }
}

请注意,如果Activator.CreateInstance&lt;T&gt; 有一个where T : new() 约束,那么上面的Cache&lt;T&gt; 类也需要那个约束,因为Create 是一个虚方法并且某些派生类可能希望使用不同的实例化方式,例如调用类型的内部构造函数或使用静态构建器方法。

【讨论】:

  • +1。这是一个很好的观点。虽然您要承担一些风险(很明显,T 可能没有默认构造函数),但这似乎是一个完全有效的案例。
  • 顺便说一句,看起来System.Runtime.CompilerServices.ConditionalWeakTable 就是这样做的。
  • 另外值得注意的是,受where T : new() 约束的CreateInstance&lt;T&gt; 方法将是完全多余的。由于T 必须在编译时已知,因此任何受where T : new() 约束的T 都可以使用var x = new T() 语法创建。
  • @LukeH:哈,是的,认为这是被问到的问题有点好笑,而如果Activator.CreateInstance&lt;T&gt; 确实 有where T : new() 约束,那么肯定会是一个 SO 问题,“Activator.CreateInstance&lt;T&gt; 到底有什么意义?”
  • @Dan, LukeH:不管怎样,对new T() 的调用实际上变成了对Activator.CreateInstance&lt;T&gt;() 的调用。
猜你喜欢
  • 2015-12-09
  • 2017-01-19
  • 2011-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-28
相关资源
最近更新 更多