简体   繁体   English

C#中的重载分辨率,扩展方法和通用性

[英]Overload resolution, extension methods and genericity in C#

I have the following scenario in my C# source: 我在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);
     }
}

When I run this code the output is: 当我运行此代码时输出为:

" D<A> chosen with a = 5" D<A>选择a = 5”

"Generic D chosen with a = 5" “选择a = 5的通用D

That result surprised me, because I was expecting " D<A> chosen with a = 5" in both situations. 这个结果让我感到惊讶,因为在这两种情况下,我都期待“ D<A> = A”选择a = 5“。

I would like to know what are the general overload resolution rules in this scenario, or anything that cause this output. 我想知道在这种情况下什么是一般的重载解析规则,或任何导致此输出的东西。 Furthermore, I wonder if there is a way to achieve the first output in both situations. 此外,我想知道是否有办法在两种情况下实现第一次输出。

Extension methods are syntactic sugar that is interpreted at compile-time using information taken from the static type system only. 扩展方法是语法糖,在编译时使用仅从静态类型系统获取的信息进行解释。

Taking your first example, you have this: 举个例子,你有这个:

dispatch.D(a);

dispatch is of type Dispatch<A> , for which an extension method exists. dispatch的类型为Dispatch<A> ,其中存在扩展方法。 So the compiler translates this into DispatchExt.D(dispatch, a) (the non-generic version). 因此编译器将其转换为DispatchExt.D(dispatch, a) (非泛型版本)。

In your second example, you have this: 在你的第二个例子中,你有这个:

d.D(a);

d is of type Dispatch<T> . d的类型为Dispatch<T> So this takes the generic extension method DispatchExt.D<T>(d, a) . 所以这采用了泛型扩展方法DispatchExt.D<T>(d, a)

Since the translation happens at compile-time, the actual run-time type is not taken into account. 由于转换发生在编译时,因此不考虑实际的运行时类型。


This is btw. 这是顺便说一句。 the same behavior used when determining overloads in other situations: Only the static compile-time type is taken into account: 在其他情况下确定重载时使用的相同行为:仅考虑静态编译时类型:

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

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

Using the following definitions: 使用以下定义:

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

I think you mean like this -- a chaining method that calls itself. 我认为你的意思是这样的 - 一种自称的链式方法。 I did a multiple calls of sum of numbers. 我做了一个数字总和的多次调用。

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;

        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM