为什么在C#中有一个new()约束,但没有其他类似的约束?


19

在C#泛型中,我们可以说,使类型参数T具有默认构造函数的约束where T : new()。但是,没有其他像这样的约束有效(new(string)例如,等等)。

从语言设计和/或实现的角度来看,这是什么原因?

构造函数的工作方式或类型系统的实现方式是否有某些禁止(或至少使之更加困难)的东西?如果是这样,那是什么?我记得读书的地方,default(T)实际上编译到new T()T : struct。可能与此有关吗?

还是仅仅是为了避免使语言过于复杂而做出的设计决定?


new(string)不是默认的构造函数约束。您的问题等于说“为什么不存在需要特定构造函数签名的约束?” 很可能因为这样的约束不是特别有用。
罗伯特·哈维

3
@RobertHarvey是的,这正是我的意思。我本质上是在问是否有某种因素使默认构造函数在特殊实现方式上有意义,或者只是一个任意选择就包括了这个,而没有另一个。
Theodoros Chatzigiannakis 2014年

默认构造函数以某些特定且重要的方式很有用。例如,它们使类型易于序列化。
罗伯特·哈维

6
特定的ctor签名可能很有用。例如,如果类型变量被限制为Collection <T>且其ctor为T(Collection <T>),则您知道可以给另一个构造新的collection。但是,这种有用性是否值得额外的复杂性是一个问题。
Phoshi 2014年

Answers:


5

有关权威的答案,请参考几年前Eric Lippert在StackOverflow上针对该问题的答案,下面简要引用其中的一小段。

但是,在这种特定情况下,我当然可以给您一些理由,说明如果在设计会议中提出该功能,并将其作为该语言的未来版本的可能功能,那么我将不推荐该功能。

...

我说我们应该要么做整个功能,要么根本不做。如果能够将类型限制为具有特定的构造函数很重要,那么让我们来做整个功能并根据一般成员(而不只是构造函数)来限制类型。


2
脱离上下文引用的那句话非常令人误解。它表明,埃里克(Eric)认为微软应该“一路走好”,这根本不是他的立场。实际上,他完全反对建议的功能。
罗伯特·哈维

1
谢谢,这确实部分回答了我的问题:答案接近尾声时,埃里克·利珀特(Eric Lippert)提到这是对IL的限制,而包括此功能将需要对IL进行补充。这将会是完美的,如果你能提供什么是该部分产生IL源实现-也就是说,一般调用默认的构造函数。
Theodoros Chatzigiannakis 2014年

@TheodorosChatzigiannakis:为什么不启动Telerik的反编译器并自己寻找?
罗伯特·哈维

2
@RobertHarvey我认为这根本没有暗示他的职位,但是我添加了另一条引述来强调他的职位。
克里斯·汉农

1
嗯,F#有更多高级方法来约束类型,例如检查类是否有运算符时的编译时间。也许,由于F#非常严格的类型检查,因此它需要比C#更强大的约束系统。但是,该语言能够实现高级方法来包含.Net Framework上的类。
OnesimusUnbound 2014年

16

对任何感兴趣的人,反编译(按照Robert Harvey的建议)得出以下结果。此方法:

static T GenericMake<T>()
    where T : new()
{
    return new T();
}

显然,在编译时变成:

private static T GenericMake<T>()
    where T : new()
{
    T t;
    T t1 = default(T);
    if (t1 == null)
    {
        t = Activator.CreateInstance<T>();
    }
    else
    {
        t1 = default(T);
        t = t1;
    }
    return t;
}
  • 如果T是值类型,则new()变为default(T)
  • 如果T是引用类型,则new()使用反射。Activator.CreateInstance()内部通话RuntimeType.CreateInstanceDefaultCtor()

这样就可以了-在内部,默认构造函数确实是C#相对于CLR而言特殊的。即使对于泛型中更复杂的约束存在一些有效的用例,给予其他构造函数相同的待遇也将是昂贵的。


4
有趣。为什么要重复调用default(T) 值类型?
Avner Shahar-Kashtan'4

2
@ AvnerShahar-Kashtan我不知道。它可能是编译/反编译过程的产物,例如t变量(可以由嵌套return语句代替)。
Theodoros Chatzigiannakis 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.