"在大多数情况下,基础抽象泛型类是一个糟糕的选择." 为什么?(或者为什么不)

Ian*_*ose 22 .net c# generics inheritance

我刚看到博客文章的评论:

在大多数情况下,基本抽象泛型类是一个糟糕的选择

这是真的,如果不是为什么?

什么见解导致了这种说法?

Jam*_*rgy 15

我同意,因为任何继承抽象泛型类的东西都不会与基类一致.也就是说,如果你有

abstract class myBase<T>

然后你创造

class myThing: myBase<thing>
class myOtherThing: myBase<otherThing>
Run Code Online (Sandbox Code Playgroud)

你不能创建适用于myThing和myOtherThing的方法,因为它们不共享祖先.基类中没有任何意义是抽象的,实际上,它也可能只是一个类.

但是如果你有一个基类

abstract class myBase
class myBase<T>: myBase
Run Code Online (Sandbox Code Playgroud)

作为泛型类的常见模式(如IEnumerable - 使用接口),它们都共享myBase.

(编辑)我刚刚阅读了实际的博客文章 - 实际上,评论在那种情况下并不真正有效.他所指的"抽象通用基类" Range<T>继承IEnumerable<T>了继承非泛型接口的东西IEnumerable.所以它并不是一个"抽象的通用基类".但一般来说我认为这是真的.


Hum*_*rto 14

"大多数情况"是完全模糊的.如果此类的后代之间唯一的共同祖先是System.Object(如此问题的其他评论者所述),则通用抽象类(或接口)是一个坏主意.

否则(如果你确实有一个有意义的共同祖先),如果你想"重命名"或"专门化"成员,这是一个好主意.考虑这个例子:

// Meaningful common ancestor for the working classes.
interface IWorker
{
   object DoWork();
}

// Generic abstract base class for working classes implementations.
abstract WorkerImpl<TResult> : IWorker
{
   public abstract TResult DoWork();

   object IWorker.DoWork()
   {
      return DoWork(); // calls TResult DoWork();
   }
}

// Concrete working class, specialized to deal with decimals.
class ComputationWorker : WorkerImpl<decimal>
{
    override decimal DoWork()
    {
       decimal res;

       // Do lengthy stuff...

       return res;
    }
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中,DoWork()在抽象类中重新定义,变得具体和专业ComputationWorker.

  • @jamietre:根据您的定义,没有类是抽象基类(通用或非通用),因为唯一的基类是`System.Object`. (2认同)
  • @jamietre:你混淆了"is-a"和"has-a"的关系. (2认同)