Jens Borrisholt
Jens Borrisholt

Reputation: 6402

How do overloaded methods work

I've been programming for may years first Delphi and now c# so I thought I knew how overloaded method worked, but apparently not.

First some code

public enum TestEnum { Option1, Option2, Option3 }

public class Setting
{
    public Setting()
    {
        AddSettings();
    }

    protected void CreateSetting<TEnum>(string AName, TEnum AValue) where TEnum : struct, IComparable, IFormattable
    {
        //do stuff
    }

    protected void CreateSetting(string AName, string AValue)
    {
        //do stuff
    }

    protected void CreateSetting(string AName, int AValue)
    {
        CreateSetting(AName, AValue.ToString());
    }

    protected void AddSettings()
    {
        CreateSetting("Language", (byte)0); //#1
        CreateSetting("BFL", "true"); //#2
        CreateSetting<TestEnum>("TestEnum", TestEnum.Option1); //#3
        CreateSetting("TestEnum", TestEnum.Option1); //#4
    }
}

I've added a number to each call to CreateSettings in order for making it easyer to explain.

My question as :

Call #1 calls the wrong (Generic) version of CreateSettings because I've made a cast to a byte but why?

Call #2 works just fine.

Call #3 works just fine as well. I explicit calls the gerneric version

Call #4 also works but with some "magic" the compiler resolves the correct (genneric) version and calls that. But why does it work?

I have figured out that #1 call the wrong version for the same reason that #4 works. I was just wondering if any one could give me an explanation.

Upvotes: 5

Views: 117

Answers (3)

Coder1409
Coder1409

Reputation: 498

Call #1

You made a constraint where TEnum : struct, IComparable, IFormattable

Which means the type TEnum is either a value type or a type that implements the two interfaces you have a byte argument which means the method that will be called is method 1 since byte is a value type and none of the other methods accepts byte as an argument

Call 2 and Call3

Works as expected

Call4

Again the compiler would resolve to the first method because Enum is a value type and none of the other method accepts the Enum type as an argument so the most appropriate overload is method 1

Upvotes: 1

Xefan
Xefan

Reputation: 663

The method called is determined by the process of overload resolution.

The compiler builds a list of possible candidate methods that could be called based on the types of the parameters passed, and then ranks them based on a set of rules that determine which method is the best option to call based on the quality of any type conversion that may occur. You can view these rules here:

https://msdn.microsoft.com/en-us/library/aa691339%28v=vs.71%29.aspx

The general overload resolution process is described here:

https://msdn.microsoft.com/en-us/library/aa691336%28v=vs.71%29.aspx

By following through these rules and comparing to each of your scenarios you should be able to see which rule you are hitting in each case.

Upvotes: 2

Mathew Thompson
Mathew Thompson

Reputation: 56429

The overloads are working as expected, you stated that:

#1 calls the wrong version

It calls the correct version because what you're doing is casting the int to a byte, so you no longer have an int variable, you have a byte. Are you expecting it to match the int overload? How could it, you've just cast the variable to a byte.

Call #4 also works but with some "magic"

This isn't magic, this works basically because of the same reason as the above, the type is neither an int or a string, so the only other possible overload it could call is the generic one because your "generic" method essentially says any other class (the type here is TestEnum)

Upvotes: 10

Related Questions