为什么创建泛型类型的实例会像这样工作?

时间:2017-03-19 11:30:39

标签: c# generics

用例:

class A {};

class B : A {};

class C : A {};

class Foo <T>: where T : A {
...

// T bar = new T(arg1, arg2);

...

}

class FooB: Foo<B> {...}

class FooC: Foo<C> {...}

我想在A的相应子项中使用班级Foo的孩子。 FooAFooB有一些额外的逻辑,分别只适用于AB。作为旁注,我希望这是正确的方法,因为我觉得这是一个常见的情况,但我还没有在其他地方看到任何信息。

编译器是否应该能够根据T必须是A的子项的约束来看到哪个构造函数是合适的?我目前只能添加new()约束,然后在新创建的对象上调用方法。这也是here in a similar question完成的。我不明白为什么编译器可以调用未知类型的方法但不能实例化它。特别是有限制,应该允许它这样做。

例如,为什么我可以这样做:

class Foo <T>: where T: A, new() {
...
T bar = new T()
bar.Construct(arg1, arg2);
...

1 个答案:

答案 0 :(得分:2)

让我们检查下一个课程:

public class A
{
    public int SomeInt { get; set; }

    public A(int someInt)
    {
        this.SomeInt = someInt;
    }
}

public class B : A
{
}

这将无法编译,因为A上没有公共默认构造函数,编译器也不知道如何从A初始化B。 构造函数不是在C#中继承的: 来自Microsoft documentation

  

与其他成员不同,实例构造函数不是继承的,并且除了在类中实际声明的实例之外,没有实例构造函数。如果没有为类提供实例构造函数,则会自动提供没有参数的空构造函数。

当然,在我们修复之后,我们可以调用SomeInt类的B属性。毕竟继承是什么。

因此,对于您的问题 - 编译器不知道在运行时将为T类型定义哪些构造函数。但是它知道,因为它是A的子类,它可以访问哪些方法/属性。