C# “我需要帮助”;这";关键词与继承

C# “我需要帮助”;这";关键词与继承,c#,inheritance,this,abstract-class,virtual-functions,C#,Inheritance,This,Abstract Class,Virtual Functions,经过上述减退后 abstract class BaseClass { public virtual void Accept(IVisitor visitor) { visitor.Visit(this); } } class DerivedClass: BaseClass { } interface IVisitor { void Visit(BaseClass baseEntity); void Visit(DerivedClass

经过上述减退后

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"
  • 有人能解释为什么吗
  • 我应该如何生成“已访问的派生实体”?我不想重写“Accept”函数

重载在编译时解决,因此在编译
基类时,编译器将选择
访问者。访问与编译时类型(
基类
)匹配的
重载

当使用访问者模式时,您通常希望在派生类中重写
Accept
方法

虽然可以使用
动态
避免这种情况,但如果这样做,将失去静态类型检查的优势


显示了C#中访问者模式的一个示例,其中
Accept
方法在派生类中被重写。

这里面临的问题是多个分派。编译器选择基类是因为您从基类调用它。您可以添加的一个快速解决方案是使用
动态

"Derived Entity visited"
您欺骗编译器不知道对象的实际类型,并调用正确的访问重载


这里有一些额外的阅读

我认为您试图以一种不太可能给出您想要的结果的方式将多态性和方法重载混为一谈。。。曾经也许应该坚持多态性。我正试图通过实现一个简单的示例来理解访问者设计模式。您的建议是重写函数,对吗?自从我实现Visitor已经有一段时间了,但我不记得它涉及到了每个方法重载;所以,是的。在阅读该文档的讨论部分,这更像是我所期望的多态性示例,虽然每个类都有访问者对象的重载(这在我看来仍然违反OCP),但派生类会覆盖它们。我不知道这是否可行,但我很确定你不想做这件事practice@MustafaDüman
dynamic
通常会导致额外的运行时开销,并有效地将duck类型插入到非常静态类型的语言中。我并不是说你不应该使用它,但它不应该只是随便乱扔。我明白你的意思。谢谢在这个示例中,如果我使用“动态”,我的代码看起来更干净。。如果我不使用它,我应该将同一个函数复制并粘贴到每个派生类中(尽管此示例中只存在一个派生类)。@MustafaDüman请参阅我的其他评论,我认为您需要此黑客攻击的原因是您错误地实现了模式。您可能还必须将访问者对象强制转换为动态,我在实践中发现了。因此,我把杰勒鲁厄普的答案标为正确答案,因为它给了我想要的。。但是@BradleyDotNet和您的评论也对使用dynamic提供了启发。非常感谢。
public virtual void Accept(IVisitor visitor)
{
    visitor.Visit(this as dynamic);
}