c# - 如何处理 C# 中缺少多重继承的问题

标签 c# oop multiple-inheritance

我正在为“可运行”的东西开发一个迷你框架。 (它们是实验、测试、任务等)

// Something that "runs" (in some coordinated way) multiple "runnable" things.
interface IRunnableOf<T> where : IRunnable

// Provide base-class functionality for a "runner"
abstract class RunnerBase<T> : IRunnableOf<T>


class SequentialRunner<T> : RunnerBase<T>  // Same interface, different behavior.
class ConcurrentRunner<T> : RunnerBase<T>
// other types of runners.

class ConcurrentBlockRunner : SequentialRunner<Block>
class SequentialBlockRunner : ConcurrentRunner<Block>

现在,我该如何协调 ConcurrentBlockRunnerSequentialBlockRunner ?我的意思是:

  1. 通过共同的祖先来引用它们,以便在集合中使用。 (IEnuerable<T> 其中 T = ??)

  2. 提供额外的基类功能。 (例如,添加属性)。


我通过添加另一个接口(interface)来补救 #1,该接口(interface)刚刚将类型参数指定给 IA<T> :

interface IBlockRunner : IRunnableOf<Block> { }

并修改了我的ConcurrentBlockRunnerSequentialBlockRunner定义为:

class ConcurrentBlockRunner : SequentialRunner<Block>, IBlockRunner
class SequentialBlockRunner : ConcurrentRunner<Block>, IBlockRunner

ConcurrentBlockRunnerSequentialBlockRunner都使用 Block对于他们的类型参数,这似乎是一个正确的解决方案。然而,我不禁对此感到“奇怪”,因为好吧,我只是把那个界面加了上去。


对于#2,我想向ConcurrentBlockRunner 添加几条公共(public)数据。和 SequentialBlockRunner .有几个属性适用于它们,但不适用于它们唯一的公共(public)基类,它一直在 RunnerBase<T>。 .

这是我第一次在使用 C# 时感觉到多重继承会有所帮助。如果我能做到:

abstract class BlockRunnerBase {
   int Prop1 { get; set; }
   int Prop2 { get; set; }

class ConcurrentBlockRunner : SequentialRunner<Block>, BlockRunnerBase
class SequentialBlockRunner : ConcurrentRunner<Block>, BlockRunnerBase

然后我可以简单地将这些额外的属性添加到 BlockRunnerBase,一切都会正常工作。有没有更好的办法?


我知道我会立即被推荐考虑composition ,我开始使用它:

class BlockRunner : IBlockRunner  {
   IBlockRunner _member;

   int Prop1 { get; set; }    // Wish I could put these in some base class
   int Prop2 { get; set; }       

   // Lots of proxy calls, and proxy events into _member
   void Method() { _member.Method(); }
   event SomeEvent
   {
      add { _member.SomeEvent += value; }
      remove { _member.SomeEvent -= value; }
   }
}

我遇到的问题(促使我写这个问题)是一旦你组合,你就失去了类型兼容性。在我的例子中,_member 触发了一个事件,所以 sender参数类型为 SequentialBlockRunner .但是,事件处理程序试图将其转换为类型 BlockRunner ,这当然失败了。那里的解决方案不使用 add/remove代理事件,但实际上处理它们,并引发我自己的事件。这么多的工作只是为了添加几个属性......

最佳答案

Composition over Inheritance , 好吧!

更明确地说:

class SequentialRunner<T> : RunnerBase<T>

应该实现IRunnableOf<T>并代理 RunnerBase<T>没有继承它。

class SequentialRunner<T> : IRunnableOf<T>
{
   private readonly RunnerBase<T> _runnerBase;

   ...
}

关于c# - 如何处理 C# 中缺少多重继承的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10988695/

相关文章:

C++ 多重继承顺序

python - 为什么我在使用 super() 时必须指定我自己的类,有没有办法绕过它?

c++ - 派生 istringstream 并实现运算符>>(string&)

c# - ExcelCom 将公式写入单元格会导致#name?

c# - WebApi 返回 HTTP 响应后是否可以执行代码?

c# - 在 C# Web 应用程序项目中推送通知

c# - 为什么 C# 不提供 C++ 风格的 'friend' 关键字?

oop - 在sysadmin/Perl/Linux背景下“赢得” OO编程工作面试?

python - python 中的组合和外观是同一件事吗?

c# - 在 C# 中设置进程名称