Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguous method overloading

Tags:

c#

overloading

This issue has caught me out once again. Could someone provide a technical explanation as to why the following code does not produce any warnings or errors. The question you have to ask yourself is (of course) do you feel 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 awarded if you know which method will be called without running the code. And just to add insult, it doesn't just happen 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));
    }
}
like image 566
adelphus Avatar asked Jan 26 '12 11:01

adelphus


People also ask

How do the overloading methods can be ambiguous?

There are ambiguities while using variable arguments in Java. This happens because two methods can definitely be valid enough to be called by data values. Due to this, the compiler doesn't have the knowledge as to which method to call.

What is ambiguous method?

This ambiguous method call error always comes with method overloading where compiler fails to find out which of the overloaded method should be used. Suppose we have a java program like below. Above program compiles perfectly and when we run it, it prints “String”. So the method foo(String s) was called by the program.

How do you overcome ambiguity in java?

The inclusion of generics gives rise to a new type of error that you must guard against ambiguity. Ambiguity errors occur when erasure causes two seemingly distinct generic declarations to resolve to the same erased type, causing a conflict. Here is an example that involves method overloading.

What is ambiguous invocation in java?

Ambiguous Invocation. □ Sometimes there may be two or more possible. matches for an invocation of a method, but the. compiler cannot determine the most specific match. This is referred to as ambiguous invocation.


1 Answers

First example: null argument

In the first case it will call the string overload. null matches both object and string, but string is the more specific/derived type. Thus it chooses string.

Check Eric Lippert's post How does the method overload resolution system decide which method to call when a null value is passed? for a longer explanation for this part of overload resolution.

Now we must determine the best of the applicable candidates. The bestness rules are complicated, but the short version is that more specific is better than less specific.

Second example: integer literal

In the second case it'll choose the first overload, because the literal 7 is int. If you had used 7u it would have been uint and thus the second overload would be preferred.

Integer literals have a well defined type(even if they allow more implicit conversions than normal integral values). You can use suffixes like u for unsigned, or l for long to influence that type. Or you can add an explicit cast.

While normally an int wouldn't be implicitly convertible to uint, this is an integer constant which is in the valid range of uint, and the C# compiler has an extra rule to allow implicit conversions between integer constants, provided the constant fits the target's range.

One 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, provided 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, provided the value of the constant expression is not negative.


In both examples one overload is clearly the best, as far as the C# compiler is concerned, and thus you don't get an ambiguous overloading error.

Personally I think that the first example should give a warning, but either the C# team disagrees, or they simply didn't have time to add that heuristic.

like image 64
CodesInChaos Avatar answered Sep 20 '22 20:09

CodesInChaos