我认为我有一个相当普遍的问题,但我真的能想出一个解决方案..
想象一下这个课程:
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#中解决。
答案 0 :(得分:3)
首先,我认为这是代码味道。我会尝试找到一些不需要这个的替代设计。但是如果不了解你想要解决的实际问题,很难帮助你。
现在,问你的实际问题:
这是一个多调度问题,如果没有访问者模式,我认为它无法在C#中解决。
这不是多个调度问题的常见版本:您调度的类型不在您的控制之下(因此您无法向其添加AcceptVisitor()
),类型列表也是每个派生类型都不同(因此您无法创建固定的IVisitor
)。
但实际上可以使用dynamic
在C#中解决此问题。确切的解决方案取决于您是否愿意公开HandleAdd()
重载。如果您可以这样做,那么只需使用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()
如果你想保持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()
方法是没有意义的,你宁愿只需将它们直接添加到相应的列表中即可。