尝试访问者模式和通用方法,我在 C#.NET 中发现了一种差异。AFAIK C# 编译器更喜欢显式重载而不是泛型方法,因此以下代码:
public abstract class A
{
public abstract void Accept(Visitor v);
}
public class B : A
{
public override void Accept(Visitor v)
{ v.Visit(this); }
}
public class C : A
{
public override void Accept(Visitor v)
{ v.Visit(this); }
}
public class D : A
{
public override void Accept(Visitor v)
{ v.Visit(this); }
}
public class Visitor
{
public void Visit(B b)
{ Console.WriteLine("visiting B"); }
public void Visit(C c)
{ Console.WriteLine("visiting C"); }
public void Visit<T>(T t)
{ Console.WriteLine("visiting generic type: " + typeof(T).Name); }
}
class Program
{
static void Main()
{
A b = new B();
A c = new C();
A d = new D();
Visitor v = new Visitor();
b.Accept(v);
c.Accept(v);
d.Accept(v);
}
}
产生的输出是(如预期的那样):
visiting B
visiting C
visiting generic type: D
但是,此访问者模式实现不允许交换访问者类。引入抽象类 VisitorBase 并将调用转发给重载会产生 smth。出乎我的意料......
public abstract class A
{
public abstract void Accept(VisitorBase v);
}
public class B : A
{
public override void Accept(VisitorBase v)
{ v.Visit(this); }
}
public class C : A
{
public override void Accept(VisitorBase v)
{ v.Visit(this); }
}
public class D : A
{
public override void Accept(VisitorBase v)
{ v.Visit(this); }
}
public abstract class VisitorBase
{
public abstract void Visit<T>(T t);
}
public class Visitor : VisitorBase
{
protected void VisitImpl(B b)
{ Console.WriteLine("visiting B"); }
protected void VisitImpl(C c)
{ Console.WriteLine("visiting C"); }
protected void VisitImpl<T>(T t)
{ Console.WriteLine("visiting generic type: " + typeof(T).Name); }
public override void Visit<T>(T t)
{
VisitImpl(t); //forward the call to VisitorImpl<T> or its overloads
}
}
class Program
{
static void Main()
{
A b = new B();
A c = new C();
A d = new D();
VisitorBase v = new Visitor();
b.Accept(v);
c.Accept(v);
d.Accept(v);
}
}
现在输出是:
visiting generic type: B
visiting generic type: C
visiting generic type: D
泛型方法只喜欢泛型方法吗?为什么不调用显式重载?