c# - 如何使用多态避免 'If cascade' 和类型转换?

标签 c# design-patterns polymorphism

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

// 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) {}
}

在 'Is passing around value objects using polymorphism a bad practice? ' Visitor模式被提出;

If 级联和强制转换的问题被移动(而不是消除)到抽象基类中。

是否有更好的解决方案来完全避免 if's?

我(在本例中)无法将功能从 doX/doY 移至类 DC_A/DC_B

非常感谢您的建议。

编辑: 这个问题的背景是一个 C#/WinForms 应用程序,它有一个表单来管理一个“测试规则”,该规则由不同的子实体组成,比如 TestSpec 和一组测量类型、测试限制等(我的 DC_A、DC_B 类)所有派生来自 EntityBase(=BC 从上面) 表单向 Controller 发送一个子实体已更改的事件; 简化的 PropertiesChanged(EntityBase o) Controller 调用模型类中的相应方法(上面 XY 类中的方法 goo),该方法现在负责执行业务逻辑,该业务逻辑不仅保留更改的子实体测试限制,而且例如创建新的测试限制修订对象,增加测试规范修订等。 也许以这种方式 具有像 PropertiesChanged(EntityBase o) 这样的方法的通用方法应该更改为来自表单的更具体的事件以及 Controller 和模型类中的特定事件处理程序以处理“TestLimitChanged”等。

但是这个特例让我想到了关于多态性的更普遍或更“哲学”的问题 ;-)

最佳答案

如果您使用的是 .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) { }
}

关于c# - 如何使用多态避免 'If cascade' 和类型转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13719780/

相关文章:

swift - 使用协议(protocol)要求的子类

c# - wcf 决定 : one service multiple contracts or many services

c# - C# 中的 4 位枚举

python - 该数据使用什么数据结构?

Java 抽象类或静态实用程序类设计选择

c++ - 派生模板类

c# - 智能感知无法识别 PUBXML 中的正确标签

c# - 在 Windows 服务器上启动 ImageMagick 进程失败,出现 "the specified module could not be found."

java - OOP 设计 - 需要准备每个方法调用并在之后清理

java - 多态性中的内存管理是怎样的?