具有继承参数的重载函数

Overloaded functions with inherited parameter

我正在尝试做这样的事情,但我收到错误,大致如下:

Cannot convert from AbstractExampleClass to SpecificExampleClassA.

所以我可能在使用这段代码时走错了方向,谁能告诉我哪里出了问题以及如何解决它。

public abstract class AbstractExampleClass 
{
    // Code goes here
}

public class SpecificExampleClassA : AbstractExampleClass 
{

}

public class SpecificExampleClass : AbstractExampleClass 
{

}

public class handler 
{
    public void Handle(AbstractExampleClass aec)
    {
        HandleSpecific(aec);
    }

    public void HandleSpecific(SpecificExampleClassA a)
    {
        // DoSomething
    }

    public void HandleSpecific(SpecificExampleClassB b)
    {
        // DoSomething Else
    }

}

重载在编译时解决,因此您不能指望它根据 aec运行时类型 来决定调用哪个重载。 要调用的重载必须在编译时决定。

你真正需要的是“subtyping" kind of polymorphism (aka just "polymorphism" in C# terminology), not ad hoc polymorphism(又名"overloading")。

改为在子类中移动处理程序方法:

public abstract class AbstractExampleClass 
{
    public abstract void Specific();
}

public class SpecificExampleClassA : AbstractExampleClass 
{

    public override void Specific()
    {
        // DoSomething
    }
}

public class SpecificExampleClass : AbstractExampleClass 
{

    public override void Specific()
    {
        // DoSomething Else
    }
}

public class handler 
{
    public void Handle(AbstractExampleClass aec)
    {
        aec.Specific();
    }
}

可以由 Visitor Pattern

处理
public abstract class AbstractExampleClass 
{
    public abstract void Accept( Handler handler );
}

public class SpecificExampleClassA : AbstractExampleClass 
{
    public override Accept( Handler handler )
    {
        handler.HandleSpecific( this );
    }
}

public class SpecificExampleClass : AbstractExampleClass 
{
    public override Accept( Handler handler )
    {
        handler.HandleSpecific( this );
    }
}

public class Handler // the Visitor
{
    public void Handle(AbstractExampleClass aec)
    {
        aec.Accept( this );
    }

    public void HandleSpecific(SpecificExampleClassA a) // visit method
    {
        // DoSomething
    }

    public void HandleSpecific(SpecificExampleClassB b) // visit method
    {
        // DoSomething Else
    }
}

如果你真的必须这样做,你可以这样做:

    public void Handle(AbstractExampleClass aec)
    {
        switch (aec)
        {
            case SpecificExampleClassA a:
                HandleSpecific(a);
                break;
            case SpecificExampleClassB b:
                HandleSpecific(b);
                break;
            default:
                throw new Exception($"What do I do with a '{aec?.GetType()}'?");
        }
    }

但如果您被允许这样做,我推荐一种类似于 Sweeper 回答中的方法。