如何通过使用多态来避免'If cascade'和类型转换?

lam*_*mpi 4 c# polymorphism design-patterns

让我们假设以下类结构具有基类BC和2个派生类DC_A和DC_B; 此外,还有一个XY类,带有一个带有BC类型参数和其他方法的methode goo()

// base class
public class BC
{
    public virtual void foo();
}

// derived class A
public class DC_A : BC
{
    public override void  foo() {}
}

// derived class B
public class DC_B : BC
{
    public override void  foo() {}
}


public class XY
{
    public void goo(BC o)
    {
        // perfectly fine using polymorphism; no Ifs' no casting, OOP at its best ;-)
        o.foo();

        // but what to do here?
        if ( (o as DC_A) != null )
        {
            doX(o as DC_A);
        }
        else if ((o as DC_B) != null)
        {
            doY(o as DC_B);
        }
    }

    private void doX(DC_A o) {}
    private void doY(DC_B o) {}
}
Run Code Online (Sandbox Code Playgroud)

在' 使用多态传递值对象是一种不好的做法?'提出访客模式;

If级联和转换的问题被移动(未消除)到抽象基类中.

有没有更好的解决方案来完全避免if?

我没有选择(在本例中)将功能从doX/doY移动到DC_A/DC_B类

非常感谢您的建议.

编辑:这个问题的背景是一个C#/ WinForms应用程序,其中包含一个管理"测试规则"的表单,其中包含不同的子实体,如TestSpec,包含一组测量类型,测试限制等(我的DC_A,DC_B类)所有派生自EntityBase(=上面的BC)表单向控制器发送一个子实体已更改的事件; 简化的PropertiesChanged(EntityBase o)控制器调用模型类中的相应方法(上面的类XY中的方法),该方法现在负责执行businesslogic,该businesslogic不仅持久化已更改的子实体测试限制,而且还创建新的测试限制修订对象,增加测试规范修订等.也许以这种方式,具有类似PropertiesChanged(EntityBase o)的方法的通用方法应该从控制器和模型类中的窗体和特定事件处理程序更改为更具说明性的事件处理"TestLimitChanged"等

但是这个特殊情况让我得到了关于多态的更通用或"哲学"的问题;-)

eis*_*tor 5

如果您使用的是.NET 4,则可能存在重载和动态类型,这可能是您的替代方案.

class Program
{
    static void Main(string[] args)
    {
        DC_A dca = new DC_A();
        DC_B dcb = new DC_B();
        XY xy = new XY();
        xy.goo(dca);
        xy.goo(dcb);
    }
}

// base class
public abstract class BC
{
    public abstract void foo();
}

// derived class A
public class DC_A : BC
{
    public override void foo() { }
}

// derived class B
public class DC_B : BC
{
    public override void foo() { }
}


public class XY
{
    //public void goo<T>(T o) where T : BC
    //{
    //    //dynamic dyn = Convert.ChangeType(o, o.GetType());
    //    //dynamic dyn = o;
    //    //gooi(dyn);
    //    gooi((dynamic)o);
    //}

    // http://smellegantcode.wordpress.com/2008/11/04/dynamic-typing-in-c-4-and-duck-generics/
    public void goo<T>(T o) where T : BC
    {
        gooi((dynamic)o);
    }

    private void gooi(DC_A o)
    {
        o.foo();
        doX(o);
    }

    private void gooi(DC_B o)
    {
        o.foo();
        doY(o);
    }

    private void gooi(BC o)
    {
        o.foo();
    }

    private void doX(DC_A o) { }
    private void doY(DC_B o) { }
}
Run Code Online (Sandbox Code Playgroud)