繁体   English   中英

泛型类型,其类型参数是抽象基类

[英]Generic type whose type parameter is an abstract base class

假设我有一个名为Animal基类和两个名为LionTiger 派生类 我还想有一个名为AnimalList<Animal>通用类型来包含Animal成员。 例如:

var list = new AnimalList<Animal>();

list.Add(new Lion());
list.Add(new Tiger());

到目前为止非常简单,但是有一个问题……我希望基类Animalabstract 也就是说, 我不想允许创建基类的实例。 但是,使基类抽象化不会令人惊讶地导致错误CS0310 (请参见下面的完整示例)。

我确实提出了一个解决方案:根据需要使基类成为非抽象类,并仅从默认(无参数)构造函数中引发异常:

public Animal()
{
    throw new System.NotImplementedException();
}

但这使我感到有些不安。 有没有更好的办法?


这是一个完整的示例,说明了我上面描述的方案:

// public class Animal {}        // OK
public abstract class Animal {}  // 'abstract' keyword causes error 'CS0310'

public class Lion : Animal {}
public class Tiger : Animal {}

public class AnimalList<T> :
    Animal
    where T : Animal, new()
{
    public void Add(T animal) {}
}

class AnimalListDemo
{
    static public void Main(string[] args)
    {
        // The following statement causes:
        // error CS0310 - 'Animal' must be a non-abstract type with a
        // public parameterless constructor in order to use it as
        // parameter 'T' in the generic type or method 'AnimalList<T>'

        var list = new AnimalList<Animal>();

        list.Add(new Lion());
        list.Add(new Tiger());
    }
}

只需删除new()约束即可。 它要求您提供一个可以通过new()实例化的类(这是所有要求的全部内容),但是抽象类显然不能做到这一点。

MSDN

新约束指定通用类声明中的任何类型参数都必须具有公共的无参数构造函数。 要使用新的约束,类型不能为abstract

在泛型参数上绝对必须具有new()约束吗? 如果删除它,它将编译,但代价是不允许在AnimalList创建T新实例。

这样做的原因是,如果您要求该类具有一个公共的,无参数的构造函数,则它不能是抽象的,因为抽象类是专门为不可创建的,但是您要求使用new()创建该类。 。 由于这些要求彼此矛盾,因此编译器会抱怨。

该解决方案似乎是一种破解,并且也不起作用,因为派生类构造函数还将调用基类构造函数(而不是完全覆盖它),并且仍会引发异常。

在问题的最后,我问:

有没有更好的办法?

从本页的有用答案得出的结论是的!

特别是,@ CodesInChaos在对我的问题发表评论时说:

通常,我会认为new()约束有点代码味道。

这让我在寻找new()约束的替代方法。 (我确实确实需要在我的类层次结构内的基类中创建泛型类型参数的实例。)

我在以下答案中找到了要寻找的东西: 创建没有新约束的T的新实例

var instanceOfT = new T(); // Before

var instanceOfT = (T)Activator.CreateInstance(typeof(T)); // After

这使我可以删除源代码中的一些new()约束。 最后,删除new()约束使我可以根据需要将中间类设置为abstract

接口可以与new约束结合使用:

public interface IAnimal {}

public abstract class Animal : IAnimal {} 

public class AnimalList<T> where T : IAnimal, new() {}

但是,您的第一行仍将失败:

var list = new AnimalList<Animal>();

AnimalList<Animal> (或AnimalList<IAnimal> )不是有效类型,因为无法构造给定的T 你确定新的是你想要什么?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM