编程语言
首页 > 编程语言> > c#泛型和非泛型方法之间的重载决策

c#泛型和非泛型方法之间的重载决策

作者:互联网

我在互联网和stackoverflow上做了一些基本搜索,当涉及泛型版本方法和非泛型版本方法时,我看到了很多关于重载解析的讨论.我知道重载解析是在编译时完成的 – 因此如果我有这个代码:

public class A<T>
{
    public void DoStuff(T value)
    {
         InternalDoStuff(value);
    }

    protected void InternalDoStuff(int value)
    {
         Console.WriteLine("Non-generic version");
    }

    protected void InternalDoStuff(T value)
    {
         Console.WriteLine("Generic version");
    }

}

public class Test
{
    static void Main (string [] args)
    {
         A<int> a = new A<int> ();
         a.DoStuff(100);
    }
}

输出将是“通用版本”,因为“InternalDoStuff”的分辨率已由编译器整理出来,编译器看到的是“在DoStuff中使用T类型参数调用InternalDoStuff”.

但是我不知道这是否会有所不同:

public class B : A <int> 
{

}

public class Test
{
    static void Main (string [] args)
    {
         B b = new B ();
         b.DoStuff(100);
    }
}

现在我可以说编译器有足够的信息来决定“B是A的特定版本”,因此调用InternalDoStuff的非泛型版本吗?

分析这种过载分辨率是否有任何一般原则?

解决方法:

第二种方法在任何意义上都与第一种方法没有区别.

从A中派生B类绝不会改变为A类生成的IL代码.B只是继承这些方法.

如果查看A类的IL代码,可以看到它编译为调用泛型版本而不是非泛型版本 –

.method public hidebysig instance void DoStuff(!T 'value') cil managed
{
    .maxstack 8
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: ldarg.1 
    L_0003: call instance void
            ConsoleApplication1.A`1<!T>::InternalDoStuff(!0) <-- Generic version
    L_0008: nop 
    L_0009: ret 
}

来自Jon Skeet的文章here

Just as a reminder, overloading is what happens when you have two
methods with the same name but different signatures. At compile time,
the compiler works out which one it’s going to call, based on the
compile time types of the arguments and the target of the method call.
(I’m assuming you’re not using dynamic here, which complicates things
somewhat.)

正如他提到的那样使用动态延迟解析直到运行时.这段代码将为您的两种方法调用非泛型版本方法 –

public void DoStuff(T value)
{
   dynamic dynamicValue = value;
   InternalDoStuff(dynamicValue);
} 

请参阅Jon SkeetEric Lippert中的答案,详细说明.

标签:c,overload-resolution,generics
来源: https://codeday.me/bug/20190612/1228086.html