如何处理C#中缺少多重继承

Jon*_*art 11 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>
Run Code Online (Sandbox Code Playgroud)

现在,我怎么能调和ConcurrentBlockRunnerSequentialBlockRunner?我的意思是:

  1. 由共同的祖先引用它们,用于集合.(IEnuerable<T>其中T = ??)

  2. 提供其他基类功能.(例如,添加属性).


我通过添加另一个只指定了类型参数的接口来补救#1 IA<T>:

interface IBlockRunner : IRunnableOf<Block> { }
Run Code Online (Sandbox Code Playgroud)

并修改我ConcurrentBlockRunnerSequentialBlockRunner定义为:

class ConcurrentBlockRunner : SequentialRunner<Block>, IBlockRunner
class SequentialBlockRunner : ConcurrentRunner<Block>, IBlockRunner
Run Code Online (Sandbox Code Playgroud)

由于ConcurrentBlockRunnerSequentialBlockRunner两者都使用Block它们的类型参数,这似乎是一个正确的解决方案.但是,我不禁对此感到"怪异",因为我刚刚在那个界面上添加了.


#2,我想普通的数据几件加入ConcurrentBlockRunnerSequentialBlockRunner.有几个属性适用于它们,但不适用于它们唯一的共同基类,这一直是最重要的RunnerBase<T>.

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

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

class ConcurrentBlockRunner : SequentialRunner<Block>, BlockRunnerBase
class SequentialBlockRunner : ConcurrentRunner<Block>, BlockRunnerBase
Run Code Online (Sandbox Code Playgroud)

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


我知道我会立即考虑合成,我开始合作:

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; }
   }
}
Run Code Online (Sandbox Code Playgroud)

我遇到的问题(驱使我写这个问题)是,一旦你撰写,你就会失去类型兼容性.在我的情况下,_member正在触发一个事件,所以sender参数是类型的SequentialBlockRunner.但是,事件处理程序试图将其强制转换为类型BlockRunner,这当然是失败的.解决方案没有使用add/ remove代理事件,但实际上处理它们,并引发我自己的事件.这么多工作只是为了添加几个属性......

blu*_*tor 2

组合优于继承,FTW!

更明确地说:

class SequentialRunner<T> : RunnerBase<T>
Run Code Online (Sandbox Code Playgroud)

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

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

   ...
}
Run Code Online (Sandbox Code Playgroud)

  • @MarkSowul 如何通过扩展方法来添加属性? (2认同)