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

前端之家收集整理的这篇文章主要介绍了如何处理C#中的多重继承缺失前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在为“可运行”的事情开发一个迷你框架. (他们是实验,测试,任务等)
  1. // Something that "runs" (in some coordinated way) multiple "runnable" things.
  2. interface IRunnableOf<T> where : IRunnable
  3.  
  4. // Provide base-class functionality for a "runner"
  5. abstract class RunnerBase<T> : IRunnableOf<T>
  6.  
  7.  
  8. class SequentialRunner<T> : RunnerBase<T> // Same interface,different behavior.
  9. class ConcurrentRunner<T> : RunnerBase<T>
  10. // other types of runners.
  11.  
  12. class ConcurrentBlockRunner : SequentialRunner<Block>
  13. class SequentialBlockRunner : ConcurrentRunner<Block>

现在,如何调和ConcurrentBlockRunner和SequentialBlockRunner?我的意思是:

>通过一个共同的祖先参考,用于收集. (IEnuerable< T,其中T = ??)
>提供额外的基类功能. (例如,添加属性).

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

  1. interface IBlockRunner : IRunnableOf<Block> { }

并将我的ConcurrentBlockRunner和SequentialBlockRunner定义修改为:

  1. class ConcurrentBlockRunner : SequentialRunner<Block>,IBlockRunner
  2. class SequentialBlockRunner : ConcurrentRunner<Block>,IBlockRunner

由于ConcurrentBlockRunner和SequentialBlockRunner都使用Block作为其类型参数,这似乎是一个正确的解决方案.不过,我忍不住感到“奇怪”,因为好的,我只是把这个界面打了.

对于#2,我想将几​​个通用数据添加到ConcurrentBlockRunner和SequentialBlockRunner.有几个属性适用于它们,但不适用于它们唯一的普通基类,它们一直在RunnerBase< T>.

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

  1. abstract class BlockRunnerBase {
  2. int Prop1 { get; set; }
  3. int Prop2 { get; set; }
  4.  
  5. class ConcurrentBlockRunner : SequentialRunner<Block>,BlockRunnerBase
  6. class SequentialBlockRunner : ConcurrentRunner<Block>,BlockRunnerBase

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

我知道我会立即考虑考虑composition,我开始使用:

  1. class BlockRunner : IBlockRunner {
  2. IBlockRunner _member;
  3.  
  4. int Prop1 { get; set; } // Wish I could put these in some base class
  5. int Prop2 { get; set; }
  6.  
  7. // Lots of proxy calls,and proxy events into _member
  8. void Method() { _member.Method(); }
  9. event SomeEvent
  10. {
  11. add { _member.SomeEvent += value; }
  12. remove { _member.SomeEvent -= value; }
  13. }
  14. }

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

解决方法

Composition over Inheritance,FTW!

要更加明确:

  1. class SequentialRunner<T> : RunnerBase<T>

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

  1. class SequentialRunner<T> : IRunnableOf<T>
  2. {
  3. private readonly RunnerBase<T> _runnerBase;
  4.  
  5. ...
  6. }

猜你在找的C#相关文章