C#:避免if(x为Foo){...} else if(x is Bar){...}用于数据结构

Jon*_*nny 6 c# data-structures

我有一系列数据结构,如:

abstract class Base {...}
class Foo : Base {...}
class Bar : Base {...}
Run Code Online (Sandbox Code Playgroud)

以及一个接受Base并根据它所依赖的子类转换它的方法:

void Convert(Base b) {
  if (b is Foo) 
    // Do the Foo conversion
  else if (b is Bar) 
    // Do the Bar conversion
...
Run Code Online (Sandbox Code Playgroud)

显然这是一个可怕的面向对象 - 转换方法必须知道Base的每个派生类,并且必须在每次扩展Base时进行更改.解决这个问题的'正常'OO方法是使每个派生类的Base负责转换自身,例如

abstract class Base {
  abstract Converted Convert();
...}
class Foo : Base {
  override Converted Convert(){...}
...}
class Bar : Base {
  override Converted Convert(){...}
...}
Run Code Online (Sandbox Code Playgroud)

但是,在我编写的代码中,Base是一个纯数据结构(只有getter和setter - 没有逻辑),而且它在另一个我无权更改的程序集中.有没有一种方法可以更好地构造代码,而不强制Base的派生类具有逻辑?

谢谢

Eri*_*ert 19

如果你这样做会疼,那就不要这样做了.根本问题是:

我有一个方法,需要Base...

由于这是根本问题,请将其删除.完全摆脱那种方法,因为它很糟糕.

替换为:

void Convert(Foo foo) {
   // Do the Foo conversion
}
void Convert(Bar bar) {
   // Do the Bar conversion
}
Run Code Online (Sandbox Code Playgroud)

现在没有任何方法可以撒谎,并说它可以转换任何 Base实际上它不能.

  • @JohnGibb:这个问题的存在在逻辑上并不意味着有一个令人愉快的解决方案.我注意到Base,Foo和Bar类的开发人员没有充分预测客户的需求.如果他们有(1)他们本身就提供了必要的代码,(2)他们会更好地设计类层次结构以实现可扩展性,或者(3)他们会设计层次结构以便Foo和Bar是唯一可能的派生类型的基础. (2认同)