【问题标题】:Overload resolution, extension methods and genericity in C#C# 中的重载解析、扩展方法和泛型
【发布时间】:2015-11-23 19:18:58
【问题描述】:

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

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

"D&lt;A&gt; 选择了 a = 5"

“使用 a = 5 选择的通用 D

这个结果让我很吃惊,因为在这两种情况下我都期待“D&lt;A&gt; 选择了 a = 5”。

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

【问题讨论】:

  • 我相信这是因为在编译时静态方法中的d.D(a) 不知道将要使用的确切类型。
  • 泛型参数类型信息不会以这种方式流经泛型方法。在您的静态D 方法中,对T 一无所知,因此D 扩展方法只有一个可能的候选者。据我所知,唯一的解决方法是在运行时使用dynamic 进行调度,或者自己检查d

标签: c# generics extension-methods c#-5.0


【解决方案1】:

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

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

dispatch.D(a);

dispatchDispatch&lt;A&gt; 类型,存在扩展方法。所以编译器将它翻译成DispatchExt.D(dispatch, a)(非通用版本)。

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

d.D(a);

d 的类型为 Dispatch&lt;T&gt;。所以这需要通用扩展方法DispatchExt.D&lt;T&gt;(d, a)

由于翻译发生在编译时,实际的运行时类型没有被考虑在内。


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

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

Test(a); // "a"
Test(b); // "b"
Test(ba); // "a"

使用以下定义:

public void Test(A a) { Console.WriteLine("a"); }
public void Test(B a) { Console.WriteLine("b"); }
public class A {}
public class B : A {}

【讨论】:

    【解决方案2】:

    我想你的意思是这样的——一个调用自身的链接方法。 我多次调用数字总和。

    using System; 
    
    namespace ConsoleApplication2
    {
        class Program
        {
            static void Main(string[] args)
            {
                var magic = new Magic();
                var sum = magic.MagicAdd(2).MagicAdd(20).MagicAdd(50).MagicAdd(20).Result;
                Console.WriteLine(sum);
                Console.ReadKey();
            }
    
        }
    
        public class Magic
        {
            public int Result { get; set; }
    
            //method chaining
            public Magic MagicAdd(int num)
            {
                this.Sum(num);
                return this;
            }
    
            public int Sum(int x)
            {
                this.Result = this.Result + x;
                return this.Result;
    
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-02-26
      • 2022-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多