Solving the problem of overload according to the method of VS 2015

I find it difficult to understand why the correct overload is not selected in this simple example. Looking at the C # 5 spec in section 7.5.3.2. A more efficient member of the function, it seems like it should be able to select an unnecessary overload, but the object parameter seems to somehow play into the solution, which I don't understand. The problem I am facing is that I cannot name a non-generic version of Foo(object) without passing an argument to object . Due to the error, it seems that it is not supported, and I hope that someone can shed light on the cause.

 public class A { public string Type { get { return "non-generic"; } } } public class A<T> { public string Type { get { return "generic"; } } } class Program { // (In reality only one of the variants below can be uncommented.) static void Main(string[] args) { // This works fine and calls the generic overload as expected A<string> x = Foo<string>("foobar"); // This results in a compile time error // CS0029: Cannot implicitly convert type 'A<string>' to 'A' A x = Foo("foobar"); // This works, but ends up calling the generic overload var x = Foo("foobar"); // This works fine and calls the non-generic overload as expected object a = "foobar"; var x = Foo(a); // This works fine and calls the non-generic overload as expected A x = Foo((object)"foobar"); // By using dynamic we're able to get rid of the compile-time error, but get a // runtime exception. // RuntimeBinderException: Cannot implicitly convert type 'A<string>' to 'A' A x = Foo((dynamic)"foobar"); Console.WriteLine(x.Type); Console.ReadLine(); } private static A Foo(object x) { return new A(); } private static A<T> Foo<T>(T x) { return new A<T>(); } } 
+4
source share
1 answer

IN

 A x = Foo("foobar"); 

C # chooses a generic method because it is more specific than not generic and does not require conversion. In fact, the C # compiler creates a copy of the Foo method and replaces the parameter of type type T concrete type string . Overload resolution is performed at compile time. At run time, a method with a string parameter is called. At run time, no common overhead is generated.

Note that for resolution only the expression on the right side of the assignment is taken into account. More specifically, C # considers the signature of the method, i.e. the parameters of the method. The type of the returned method is not related to its signature.

The general method returns A<T> , but since A<T> not inferred from A , the result of type A<T> method Foo<T>() cannot be assigned x , which is of type A The same is true for the dynamic example: there is no valid conversion from A<T> to A Since overload resolution is performed during compilation, the speaker cannot solve your problem. Dynamics does its β€œwork” (ie, Binding) at run time.

Again, this is not the result you expect from a method that determines which overload is used, but the (static) arguments passed to this method.


Another example that helps clarify the facts:

 var x = Foo(5); var y = Foo("hello"); 

At compile time, C # creates two copies of the Foo method! One with int and one with string instead of the type parameter parameter T No conversion occurs at run time; not even boxing (unlike Java, which would wrap an int in an object).

+2
source

All Articles