C# 关于方法的参数类型的多态性

C# 关于方法的参数类型的多态性,c#,C#,我想我有一个很常见的问题,但我真的能想出一个解决办法 想象一下这个班级: public class ListHandlerBase { public virtual void Add(object item) { // XXX } } public class ListHandler : ListHandlerBase { List<object> ObjectList = new List<object>();

我想我有一个很常见的问题,但我真的能想出一个解决办法

想象一下这个班级:

public class ListHandlerBase
{
    public virtual void Add(object item)
    {
        // XXX
    }
}


public class ListHandler : ListHandlerBase
{
    List<object> ObjectList = new List<object>();
    List<string> StringList = new List<string>();
    List<int> IntList = new List<int>();

    public override void Add(object item)
    {
        HandleAdd(item);
    }

    private void HandleAdd(object item)
    {
        ObjectList.Add(item);
    }

    private void HandleAdd(string item)
    {
        StringList.Add(item);
    }

    private void HandleAdd(int item)
    {
        IntList.Add(item);
    }
}
我必须把所有的类型都列一个完整的清单,这听起来并不是解决这个问题的好办法

是否有任何方法可以按我想要的方式调用“正确”的方法


更新:为了使问题更加复杂,我添加了一个基类。这就是为什么我不能有多个add方法,因为基类不知道ListHandler可以接受什么对象类型。调用ListHandler类的类不知道其细节。我也认为我可以自己回答我的问题。这是一个多分派问题,如果没有访问者模式,我不认为它在C#中无法解决。

对于要处理的其他类型,您需要添加
add
的重载

public class ListHandler
{
    List<object> ObjectList = new List<object>();
    List<string> StringList = new List<string>();
    List<int> IntList = new List<int>();

    public void Add(object item)
    {
        HandleAdd(item);
    }

    public void Add(string item)
    {
        HandleAdd(item);
    }

    public void Add(int item)
    {
        HandleAdd(item);
    }

    private void HandleAdd(object item)
    {
        ObjectList.Add(item);
    }

    private void HandleAdd(string item)
    {
        StringList.Add(item);
    }

    private void HandleAdd(int item)
    {
        IntList.Add(item);
    }
}
公共类ListHandler
{
List ObjectList=新列表();
List StringList=新列表();
List IntList=新列表();
公共作废添加(对象项)
{
手持(项目);
}
公共无效添加(字符串项)
{
手持(项目);
}
公共无效添加(整数项)
{
手持(项目);
}
私有无效HandleAdd(对象项)
{
ObjectList.Add(项);
}
私有无效HandleAdd(字符串项)
{
StringList.Add(项目);
}
专用无效手动引线(内部项目)
{
IntList.Add(项目);
}
}

编辑:正如Elvedin指出的那样-当然,如果您的方法没有做更多的事情,那么保留单独的
HandleAdd()
方法是没有意义的,您可以直接将它们添加到适当的列表中。

首先,我认为这是一种代码气味。我会尝试寻找一些不需要这个的替代设计。但是,如果不了解您试图解决的实际问题,就很难帮助您解决这个问题

现在,谈谈你的实际问题:

这是一个多分派问题,我认为如果没有访问者模式,在C#中是无法解决的

这并不是多分派问题的常见版本:您分派的类型不在您的控制之下(因此您无法向它们添加
AcceptVisitor()
),并且每个派生类型的类型列表也不同(因此您无法创建固定的
IVisitor

但实际上,您可以在C#中使用
dynamic
解决这个问题。确切的解决方案取决于您是否愿意公开
HandleAdd()
重载。如果您可以这样做,那么只需从
Add()
调用
HandleAdd()
,对
项使用
dynamic

public abstract class ListHandlerBase
{
    public void Add(object item)
    {
        ((dynamic)this).HandleAdd((dynamic)item);
    }
}

public class ListHandler : ListHandlerBase
{
    List<object> ObjectList = new List<object>();
    List<string> StringList = new List<string>();
    List<int> IntList = new List<int>();

    public void HandleAdd(object item)
    {
        ObjectList.Add(item);
    }

    public void HandleAdd(string item)
    {
        StringList.Add(item);
    }

    public void HandleAdd(int item)
    {
        IntList.Add(item);
    }
}

我建议您为所需的每种类型添加一个
Add
方法重载。您能给出一个更“真实”的例子,说明您发现自己面临这个问题的情况吗?可能有更好的设计,这意味着你不必首先处理这个问题。这没关系,但使用两种方法是不必要的,如果可以的话,删除
HandleAdd
。这是真的:)但可能还有其他原因来拆分这个问题,所以我将其保留在问题附近。我理解这一点,但询问的用户可能不会。保持细节总是一个好习惯。(您已经得到+1)我不是dynamic的超级粉丝,但这个解决方案确实可以做到这一点!它强制应用程序在运行时(当我知道对象的类型时)而不是在编译时选择HandleAdd的正确版本。我不知道你能做到这一点。这就是我一直在寻找的答案。:)
public abstract class ListHandlerBase
{
    public void Add(object item)
    {
        ((dynamic)this).HandleAdd((dynamic)item);
    }
}

public class ListHandler : ListHandlerBase
{
    List<object> ObjectList = new List<object>();
    List<string> StringList = new List<string>();
    List<int> IntList = new List<int>();

    public void HandleAdd(object item)
    {
        ObjectList.Add(item);
    }

    public void HandleAdd(string item)
    {
        StringList.Add(item);
    }

    public void HandleAdd(int item)
    {
        IntList.Add(item);
    }
}
public abstract class ListHandlerBase
{
    public abstract void Add(object item);
}

public class ListHandler : ListHandlerBase
{
    …

    public override void Add(object item)
    {
        HandleAdd((dynamic)item);
    }

    …
}