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

标签 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 方法接受非常通用的类型对象。然而,有几种方法可以处理对象,但只有“HandleAdd(object item)”会被调用,因为 item 是对象类型(即使它实际上是一个字符串)。为此,我想要某种虚拟/覆盖。

有一个丑陋的解决方案可能看起来像这样:

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

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

无论如何我都可以按照我想要的方式调用“正确”的方法吗?

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

最佳答案

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

现在,针对您的实际问题:

It's a multiple dispatch problem and I don't think it can not be solved in C# without the visitor pattern.

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

但您实际上可以在 C# 中使用 dynamic 解决此问题.确切的解决方案取决于您是否愿意制作 HandleAdd()重载 public 与否。如果你能做到,那就调用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()私有(private)的,那么你将不得不从派生类本身调用它。这意味着制作 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);
    }

    …
}

关于c# - 关于方法参数类型的多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22805826/

相关文章:

c# - 在C#中存储读者信息

c# - C# 中没有精度的千位分隔符

c# - 获取/设置为不同的类型

c# - Entity Framework 中的字符串匹配问题。适用于字符串文字但不适用于字符串变量

c# - 如何模拟 JsonReader 单元测试自定义 JsonConverter

c# - 将空字符串作为 SelectedValue 添加到 selectList

c# - 在 MonoTouch 中有一个 NSFetchRequest 和一个 NSPredicate 支持

c# - 来自数据源的 Linq 查询,其中...像 '%%' 或 ...像 '%%'

c# - 创建路径不存在的文件?

C# 状态模式和事件