Ambiguous Method Overload

This problem once again caught me. Can someone give a technical explanation why the following code does not cause any warnings or errors. The question that you should ask yourself (of course), are you lucky?

class Program { static string Feeling(object o) { return "Lucky"; } static string Feeling(string s) { return "Unlucky"; } static void Main(string[] args) { Console.WriteLine("I feel " + Feeling(null)); } } 

Bonus points are awarded if you know which method will be called without running the code. And just to add insult, this happens not only with null parameters:

 class Program { static string Feeling(int i) { return "Lucky"; } static string Feeling(uint i) { return "Unlucky"; } static void Main(string[] args) { Console.WriteLine("I feel " + Feeling(7)); } } 
+4
c # overloading
Jan 26 '12 at 11:17
source share
2 answers

First example: null argument

In the first case, this will cause string overloading. null matches both object and string , but the string is a more specific / derived type. So he selects string .

Check Eric Lippert message How does the method overload processing system decide which method to call when passing null? for a more detailed explanation of this part of overload resolution.

Now we must determine the best candidates. The best seller rules are complex, but the short version is that the more specific is better than the less specific.

Second example: integer literal

In the second case, he will choose the first overload, because the letter 7 is int . If you used 7u , that would be uint , and therefore a second overload would be preferable.

Integer literals are of a clearly defined type (even if they allow more implicit conversions than normal integral values). You can use suffixes of type u for unsigned or l to influence this type for a long time. Or you can add an explicit cast.

Although usually int will not be implicitly converted to uint , it is an integer constant that is in the valid range of uint , and the C # compiler has an additional rule allowing implicit conversion between integers of a constant if the constant matches the target range.

Once again, Eric explains the details: Why does this implicit conversion from int to uint work?

A constant expression of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong if the value of the constant expression is within the range of the destination type. A constant expression of type long can be converted to type ulong if the value of the constant expression is not negative.




In both examples, one overload is certainly the best with the C # compiler, and therefore you are not getting an ambiguous overload error.

Personally, I think that the first example should give a warning, but either the C # team does not agree, or simply did not manage to add this heuristic.

+9
Jan 26 '12 at 11:20
source share

The simple answer is that it does not give any errors or warnings, because it is completely valid code according to the C # specification.

The corresponding section of the C # 4 specification is 7.5.3 overall (for the whole process) and 7.5.3.2 to determine which of the appropriate function members is better when the first phase has detected more than one. (Subsequent sections, such as 7.5.3.5, provide details on "best conversion targets," etc.).

Trying to explain the rules is absolutely correct, but in a short space it would be difficult to say, unfortunately. I suggest you study this part of the specification very carefully.

+2
Jan 26 '12 at 11:26
source share



All Articles