为什么new()通用约束不能在构造函数中使用可选参数的类满足? [英] Why isn't the new() generic constraint satisfied by a class with optional parameters in the constructor?

查看:237
本文介绍了为什么new()通用约束不能在构造函数中使用可选参数的类满足?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码无法编译,生成Widget必须是带有public无参构造函数的非抽象类型错误。我认为编译器有它所需要的所有信息。这是一个错误?监督?或者有一些情况下,这将是无效的吗?

The following code fails to compile, producing a "Widget must be a non-abstract type with a public parameterless constructor" error. I would think that the compiler has all of the information it needs. Is this a bug? An oversight? Or is there some scenario where this would not be valid?

public class Factory<T> where T : new()
{
    public T Build()
    {
        return new T();
    }
}

public class Widget
{
    public Widget(string name = "foo")
    {
        Name = name;
    }

    public string Name { get; set; }
}

public class Program
{
    public static void Main()
    {
        var widget = new Widget(); // this is valid
        var factory = new Factory<Widget>(); // compiler error
    }
}


推荐答案

虽然这在逻辑上应该工作,但不幸的是没有。 CLR仍然把你的构造函数看作是一个基于参数的构造函数。

While this logically should work, it unfortunately does not. The CLR still sees your constructor as a parameter-based constructor.

请记住,虽然C#支持可选参数,但是这是在编译时在编译时完成的。底层类型仍然只包含一个构造函数接受单个参数。就CLR而言,默认参数被转换为属性,如下:

Remember that, while C# supports optional parameters, this is done at the compiler level, at compile time. The underlying type still only contains a constructor taking a single parameter . As far as the CLR is concerned, the "default parameters" are converted to attributes, like so:

public Widget(([Optional, DefaultParameterValue("foo")] string name) { // ...



<一个多语言运行时,所有语言的CLR级别都使用泛型,所以在没有默认参数的语言中约束必须是真的。语言不需要理解OptionalAttribute,也不需要DefaultParameterValueAttribute,所以这个

The CLR is a multi-language runtime. Generics are made to work at the CLR level, for all languages, so the constraints must be true in languages without default parameters, as well. Languages are not required to understand the OptionalAttribute, nor the DefaultParameterValueAttribute, so this cannot work uniformly for all languages, hence it's not allowed.

编辑:

响应你的意见:


我不明白的是为什么C#编译器不能生成必要的代码满足CLR

What I don't understand is why the C# compiler cannot generate the necessary code to satisfy the CLR

理论上,C#编译器团队可以让语言生成两个单独的构造函数,而不是一个标记有属性的构造函数。这将潜在地爆炸到许多构造函数中,因为命名参数创建了许多,许多可能的构造函数(或方法调用)的组合的能力,尤其是当有多个参数可用时。我个人很高兴他们没有,因为它会导致混乱,由于过多的方法和构造函数在生成的类型,这将导致公共API看起来与生成它的代码非常不同。使用以下构造函数:

Theoretically, the C# compiler team could have the language generate two separate constructors, instead of one constructor marked with attributes. This would, potentially, explode into many constructors, as named parameters create the capabilities for many, many possible combinations of "constructors" (or method calls for methods), especially when multiple arguments are available. I personally am glad that they did not, since it would cause confusion due to an overabundance of methods and constructors in the generated types, which would cause the public API to look very different than the code that generated it. Take the following constructor:

public Widget(
          int id = 0, 
          string name = "foo", 
          float width=1.0f, 
          float height=1.0f, 
          float depth=1.0f
       ) { // ... 

如果要在此处自动生成所有可能的组合,编译器需要为此生成 120 构造函数单个构造函数,因为有N!可能的方法来调用此...

Were you to automatically generate all of the possible combinations here, the compiler would need to generate 120 constructors for this single constructor, since there are N! possible ways to call this...

这篇关于为什么new()通用约束不能在构造函数中使用可选参数的类满足?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆