C# 中的重载解析、扩展方法和泛型

Rau*_*nso 5 c# generics extension-methods c#-5.0

我的 C# 源代码中有以下场景:

class A{}

class Dispatch<T>{}

static class DispatchExt
{
    public static void D<T>(this Dispatch<T> d, int a)
    {
         Console.WriteLine("Generic D chosen with a = " + a.ToString());
    }

    public static void D(this Dispatch<A> d, int a)
    {
         Console.WriteLine("D<A> chosen with a = " + a.ToString());
    }
}

class Program
{
     static void D<T>(Dispatch<T> d, int a)
     {
          d.D(a);
     }

     static void Main(string[] args)
     {
         int a = 5;
         var dispatch = new Dispatch<A>();
         dispatch.D(a);
         D(dispatch, a);
     }
}
Run Code Online (Sandbox Code Playgroud)

当我运行此代码时,输​​出是:

D<A>选择 a = 5”

D选择 a = 5 的通用”

这个结果让我感到惊讶,因为我期待D<A>在这两种情况下“选择 a = 5”。

我想知道这种情况下的一般重载解析规则是什么,或者导致此输出的任何内容。此外,我想知道是否有办法在这两种情况下实现第一个输出。

pok*_*oke 4

扩展方法是在编译时仅使用从静态类型系统获取的信息进行解释的语法糖。

以你的第一个例子为例,你有这样的:

dispatch.D(a);
Run Code Online (Sandbox Code Playgroud)

dispatch类型为Dispatch<A>,其存在扩展方法。因此编译器将其翻译为DispatchExt.D(dispatch, a)(非通用版本)。

在你的第二个例子中,你有这样的:

d.D(a);
Run Code Online (Sandbox Code Playgroud)

d属于 类型Dispatch<T>。所以这需要通用扩展方法DispatchExt.D<T>(d, a)

由于翻译发生在编译时,因此不考虑实际的运行时类型。


顺便说一句,这是。在其他情况下确定重载时使用相同的行为:仅考虑静态编译时类型:

A a = new A();
B b = new B();
A ba = b;

Test(a); // "a"
Test(b); // "b"
Test(ba); // "a"
Run Code Online (Sandbox Code Playgroud)

使用以下定义:

public void Test(A a) { Console.WriteLine("a"); }
public void Test(B a) { Console.WriteLine("b"); }
public class A {}
public class B : A {}
Run Code Online (Sandbox Code Playgroud)