C#泛型方法重载抽象访问者模式并不一致 [英] c# generic method overload not consistent with abstract Visitor pattern

查看:169
本文介绍了C#泛型方法重载抽象访问者模式并不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Visitor模式和通用方法实验,我发现在C#.NET是一种差异。据我所知C#编译器更喜欢一个明确的过载到一个通用的方法,因此下面的代码:

experimenting with Visitor pattern and generic method I found a kind of discrepancy in C#.NET. AFAIK C# compiler prefers an explicit overload to a generic method, therefore the following code:

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);
    }
}



所生成的输出(如预期):

The output produced is (as expected):

visiting B
visiting C
visiting generic type: D

然而,这Visitor模式实现不允许交换访问者类。引入一个抽象类VisitorBase和转发调用重载产生不便。意外的我....

However this Visitor pattern implementation does not allow to exchange the Visitor class. Introducing an abstract class VisitorBase and forwarding the call to the overloads produces smth. unexpected for me....

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

不要泛型方法只喜欢泛型方法?为什么没有明确重载叫什么名字?

Do generic methods only prefer generic methods? Why are no explicit overloads called?

非常感谢,结果
Ovanes

Many thanks,
Ovanes

推荐答案

据我了解,我可能是非常错误的,在编译时泛型函数访问实际执行某种原始类型的拆箱。虽然我们可以在逻辑上看到,类型应在编译时运行通过,C#编译不能通过访问功能的VisitImpl函数使其在保持类型,所以原始b.visit(ⅴ)被认为是在编译装箱。鉴于此,它必须通过通用相匹配时,访问方法被调用,所有类型的路线

As I understand it, and I could be very wrong, at compile time the generic function visit actually performs a sort of unboxing of the original type. While we can logically see that the types should run through at compile time, the C# compiler can't make it through the Visit function to the VisitImpl function while holding the types, so the original b.visit(v) is considered unboxed at compile. Given this, it must route through the generic for all types that match when the Visit method is called.

编辑:为了澄清我的意思,因为我刚刚看了我的废话

To clarify what I mean because I just read my own crap:

编译器存放着通用通话的链接b.Visit。它适合并标有通用的。
编译器适用于Visit-> VisitImpl单独的链接,根据需要输入和/或通用的方法。
编译器不能保存来自b.Visit链接(如通用) - > VisitImpl的类型。因为从b.Visit()的路径 - > VisitImpl必须通过一个通用的,它拥有这是一个通用型等通用VisitImpl是首选

The compiler holds the link for b.Visit as a generic call. It fits and is labeled generic. The compiler holds separate links for Visit->VisitImpl as typed and/or generic methods as necessary. The compiler can not hold a link from b.Visit (as generic) -> VisitImpl as typed. Since the path from b.Visit() -> VisitImpl must go through a generic, it holds it as a generic type and so the generic VisitImpl is preferred.

这篇关于C#泛型方法重载抽象访问者模式并不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆