我想我有一个很常见的问题,但我真的可以想出一个解决方案..
想象一下这个类:
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
对于 this
和 item
:
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/