【发布时间】:2014-01-31 14:47:40
【问题描述】:
假设我有一个名为Animal 的基类和两个名为Lion 和Tiger 的派生类。我还想要一个名为AnimalList<Animal> 的通用类型 来包含Animal 的成员。例如:
var list = new AnimalList<Animal>();
list.Add(new Lion());
list.Add(new Tiger());
到目前为止非常简单,但有一个问题...我希望基类 Animal 是 abstract。也就是说,我不想允许创建基类的实例。但是,将基类抽象化会导致错误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()约束有点代码味道。 -
正如@CodesInChaos 建议的那样,它不是
abstract关键字,而是new()约束:rextester.com/LXDH46444 -
无论如何都限制在抽象类的泛型定义有什么好处?为什么不只是
class AnimalList : Animal, IList<Animal>? -
@CodesInChaos - 你的评论让我走上了正轨。请参阅my answer。
-
@LorentzVedeler - 你说得很好。我真实代码中的模式实际上包括层次结构中的另一个级别:
abstract class AnimalList<Animal> : Animal, IList<Animal>和class ExtendedLionList : AnimalList<Lion>。
标签: c# generics abstract-class