【问题标题】:Generic type constraint of new() and an abstract base classnew() 的泛型类型约束和抽象基类
【发布时间】:2013-08-10 04:54:00
【问题描述】:

这里我们有一个简单的类层次结构,并使用具有type constraintnew() 的泛型

public abstract class Base 
{
}

public class Derived : Base
{
}

public class TestClass
{
    private void DoSomething<T>(T arg) where T : new()
    {
    }

    public void TestMethod()
    {
        Derived d1 = new Derived();
        DoSomething(d1); // compiles

        Base d2 = new Derived();
        DoSomething(d2); // compile error
    }
}

代码在指定行编译失败,错误为:

“Base”必须是具有公共无参数构造函数的非抽象类型,才能将其用作泛型类型或方法“Foo.DoSomething(T)”中的参数“T”

这个错误很清楚也很有意义,但我希望编译器能够理解Base 的所有派生(此时可以实例化)确实有一个公共的无参数构造函数。

这对编译器来说理论上可行吗?

【问题讨论】:

  • 比起无参数构造函数子句,更让我担心的是这一行non-abstract type

标签: c# generics abstract-class base-class


【解决方案1】:

唉,你必须明确地给出类型

DoSomething<Derived>(d2);

理论上不可能创造出抽象的东西

【讨论】:

  • 我喜欢“理论上”的部分。让我觉得 Jon Skeet 会突然出现,做一些魔术,然后你就可以实例化抽象对象了。
  • 如果 d2 被声明为抽象 Base,它会在哪个版本的 .NET 上编译?
【解决方案2】:

new Constraint (C# Reference):

要使用新的约束,类型不能是抽象的。

调用:

Base d2 = new Derived();
DoSomething(d2);

你实际上在做:

Base d2 = new Derived();
DoSomething<Base>(d2);

由于Base是抽象的,所以会出现编译错误。

所以,你必须明确地转换:

Base d2 = new Derived();
DoSomething((Derived) d2);

你怎么能确保编译器,任何人都放在那里的东西不是抽象的?

我看到的唯一方式是,如果我们有一个像“must-inherit-to-non-astract”这样的关键字,然后创建public must-inherit-to-non-abstract abstract class Base。之后,编译器可以确定,如果您将基实例放入您的方法中,那实际上将是一个子类,它是非抽象的,因此可以实例化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多