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

时间:2014-04-02 08:38:11

标签: c#

我认为我有一个相当普遍的问题,但我真的能想出一个解决方案..

想象一下这个课程:

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方法接受非常通用的类型对象。但是有几种方法可以处理对象,但只有&#34; HandleAdd(对象项)&#34;将被调用,因为item是object类型(即使它真的是一个字符串)。我想要一些虚拟/覆盖。

有一个丑陋的解决方案可能如下所示:

    public void Add(object item)
    {
        if(item is string) HandleAdd((string)item);
        else if (item is int) HandleAdd((int)item);
        else HandleAdd(item);
    }   

我必须列出所有类型的完整列表,这听起来并不是解决问题的好方法。

无论如何,我可以得到正确的&#34;方法按我想要的方式调用?

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

2 个答案:

答案 0 :(得分:3)

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

现在,问你的实际问题:

  

这是一个多调度问题,如果没有访问者模式,我认为它无法在C#中解决。

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

但实际上可以使用dynamic在C#中解决此问题。确切的解决方案取决于您是否愿意公开HandleAdd()重载。如果您可以这样做,那么只需使用HandleAdd() Add()dynamic thisitem拨打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); } }

HandleAdd()

如果你想保持Add()私有,那么你必须从派生类本身调用它。这意味着在基类中使dynamic抽象,并在每个派生类中使用dynamic实现它(这次,this上不需要public abstract class ListHandlerBase { public abstract void Add(object item); } public class ListHandler : ListHandlerBase { … public override void Add(object item) { HandleAdd((dynamic)item); } … } ):< / p>

{{1}}

答案 1 :(得分:1)

您需要为要处理的其他类型添加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);
    }
}

编辑:正如Elvedin所指出的那样 - 当然,如果你的方法做得不够,那么保持单独的HandleAdd()方法是没有意义的,你宁愿只需将它们直接添加到相应的列表中即可。