abstract class BaseClass
{
public virtual void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
}
class DerivedClass: BaseClass
{
}
interface IVisitor
{
void Visit(BaseClass baseEntity);
void Visit(DerivedClass derivedEntity);
}
class Visitor : IVisitor
{
public void Visit(DerivedClass derivedEntity)
{
Debug.WriteLine("Derived Entity visited");
}
public void Visit(BaseClass baseEntity)
{
Debug.WriteLine("Base Entity visited");
}
}
在上述判决之后
class Program
{
static void Main(string[] args)
{
DerivedClass derived = new DerivedClass();
Visitor visitor = new Visitor();
derived.Accept(visitor);
}
}
产生
"Base Entity visited"
然而我希望它能产生
"Derived Entity visited"
答案 0 :(得分:2)
在编译时解决了重载,因此在编译BaseClass
时,编译器将选择与其编译时类型(Visitor.Visit
)匹配的BaseClass
重载。
使用访问者模式时,通常需要覆盖派生类中的Accept
方法。
虽然您可以使用dynamic
来避免这种情况,但如果您这样做,则会失去静态类型检查的优势。
This article显示了C#中访问者模式的示例,其中Accept
方法在派生类中被覆盖。
答案 1 :(得分:1)
您面临的问题是多次调度。编译器选择基类,因为您是从基类调用它。您可以添加的一个快速解决方案是使用dynamic
:
public virtual void Accept(IVisitor visitor)
{
visitor.Visit(this as dynamic);
}
您欺骗编译器不知道对象的实际类型 - 并调用正确的访问重载。
以下是MSND
的额外阅读