Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do overloaded methods work

Tags:

c#

.net

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.

like image 812
Jens Borrisholt Avatar asked Apr 21 '15 08:04

Jens Borrisholt


2 Answers

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)

like image 157
mattytommo Avatar answered Nov 08 '22 01:11

mattytommo


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.

like image 44
Xefan Avatar answered Nov 07 '22 23:11

Xefan