重载方法..为什么基类具有优先权?

mik*_*010 5 c# c#-4.0

在下面的代码中,我有一个重载方法,一个采用ClazzA类型的参数,另一个采用ClazzB类型.在显示的代码中,调用第一个GetDescription方法(以ClazzA作为参数的方法).我想我理解为什么.
我的问题是..如果底层对象的类型是classB(不必检查每个对象并将其转换为clazzB),那么有一种优雅的方法可以使clazzB首先调用?

public class ClazzA
{
    public virtual string Descr { get { return "A"; } }
}

public class ClazzB : ClazzA
{
    public override string Descr { get { return "B"; } }
}

public static class test
{
    public static void Main()
    {
        ClazzA test = new ClazzB();
        GetDecription(test);
    }

    public static void GetDecription(ClazzA someClazz)
    {
        Debug.WriteLine("I am here");
    }

    public static void GetDecription(ClazzB someClazz)
    {
        Debug.WriteLine("I want to be here");
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:"我在这里"

我真的希望调用第二种方法,因为'test'是ClassB类型.我唯一有两个解决方案是:

  1. if(test是ClazzB)返回GetDescription((ClazzB)测试);

要么

  1. 在ClassA中做几乎相同的事情...检查类型并委托第二种方法

这两者都需要检查对象以确定其类型

Mik*_*ray 8

Overloads are determined at compile time. The compile time type of the reference is ClazzA so that overload is chosen. What you are asking for is related to multiple dispatch. C# and many other languages like C++ and Java only support single dispatch (via virtual methods). There are a number of ways people have come up with to work around this. The purest OO way of doing this is the visitor pattern. You modify the classes to contain a method (Accept) which then passes the this reference to a method on the visitor (Visit). This works because you override the Accept method in each subclass so that this will be the object's actual type. All the visitor needs is a specific method for each subclass that you want to support (see wikipedia for more details).

A sample:

public class ClazzA
{
   public virtual string Accept(ClassVisitor visitor)
   {
      return visitor.Visit(this);
   }
}

public class ClazzB : ClazzA
{
   public override string Accept(ClassVisitor visitor)
   {
      return visitor.Visit(this);
   }
}

public abstract class ClassVisitor
{
  public abstract string Visit(ClazzA a);
  public abstract string Visit(ClazzB b);
}

public class GetDescriptionVisitor : ClassVisitor
{
    public override string Visit(ClazzA a)
    {
       return "A";
    }

    public override string Visit(ClazzB b)
    {
       return "B";
    }
}
Run Code Online (Sandbox Code Playgroud)

Usage:

ClassVisitor visitor = new GetDescriptionVisitor();
ClazzA b = new ClazzB();
Console.WriteLine(b.Accept(visitor)); // prints "B"
Run Code Online (Sandbox Code Playgroud)

  • 从.NET 4开始,可以使用`dynamic`关键字在C#中进行动态调度:`GetDescription((dynamic)test);`:Prints`"我想要在这里" (5认同)