Which C# method overload is chosen?

后端 未结 4 1516
没有蜡笔的小新
没有蜡笔的小新 2020-12-10 01:23

Why is the generic method called when both overloads would match?

public static void method1(object obj)
{
    Console.WriteLine(\"Object\");
}

public stati         


        
相关标签:
4条回答
  • 2020-12-10 02:05

    Because you are already passing in T as a parameter so you don't need to type out method1<string>("xyz");you can just go method1("xyz");, .Net already knows it's a string. If you had method1 then it would be a different story.

    Also since method1(object obj) doesn't take in a string as parameter it will favor the generic function first where it can infer T. If you were to change method1(object obj) to method1(string obj) it would favor it first then the generic.

    0 讨论(0)
  • 2020-12-10 02:06

    C# will always choose the most specific method it can.

    When compiling

    method1("xyz");
    

    it will look for all methods with the specified name and then attempt to match parameters. The compiler will choose the method that is the most specific, in this case it would prefer

    method1(string s)
    

    over

    method1<T>(T t) with T = string
    

    and lastly

    method1(object o)
    

    Please note @Erik's excellent answer for an example where the compiler fails to decide.

    0 讨论(0)
  • 2020-12-10 02:12

    Overloads are resolved by choosing the most specific overload. In this case, method1<string>(string) is more specific than method1(object) so that is the overload chosen.

    There are details in section 7.4.2 of the C# specification.

    If you want to select a specific overload, you can do so by explicitly casting the parameters to the types that you want. The following will call the method1(object) overload instead of the generic one:

    method1((object)"xyz"); 
    

    There are cases where the compiler won't know which overload to select, for example:

    void method2(string x, object y);
    void method2(object x, string y);
    
    method2("xyz", "abc");
    

    In this case the compiler doesn't know which overload to pick, because neither overload is clearly better than the other (it doesn't know which string to implicitly downcast to object). So it will emit a compiler error.

    0 讨论(0)
  • 2020-12-10 02:15

    How method overloading works

    To find the matching signature of a method for a call, the compiler search in the type hierarchy from bottom to top as well in virtual table:

    • First in the class hierarchy,
    • Then in the interface hierarchy.

    Because classes prevail on interfaces.

    Indeed, before being of type of an interface, an object is of type of a class first of all.

    And non generic signatures prevail over generic as reality and facts prevail over abstraction, unless using the generic parameter allow a call on the more specialized type of instance.

    Applying the theory to the question

    This call:

    method1("xyz");
    

    Match perfectly with:

    void method1<T>(T t) { }
    

    Before matching with:

    void method1(object obj)
    

    Because string is a specialized object and it can be used as a generic parameter to be more acurate.

    On the other side, if you write:

    void method1(string obj) { }
    
    void method1<T>(T t) { }
    

    The first method is so called.

    Case study

    var instance = new List<string>();
    
    MyMethod(instance);
    MyMethod((IEnumerable<string>) instance);
    MyMethod<string>(instance);
    MyMethod((object)instance);
    
    void MyMethod<T>(List<T> instance) { }
    
    void MyMethod<T>(IEnumerable<T> list) { }
    
    void MyMethod<T>(T instance) { }
    
    void MyMethod(object instance) { }
    
    • The first call calls the first method because instance is type of List (type matching).

    • The second call calls the second method because of the side cast (implementation).

    • The third call calls the third method because of the generic parameter specified to act on (templating).

    • The fourth call calls the fourth method because of the down cast (polymorphism).

    0 讨论(0)
提交回复
热议问题