Reputation: 6402
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
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
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
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