Sunday 22 May 2016

Overloading

Overloading

          Just as a reminder, overloading is what happens when you have two methods with the same name but different signatures. At compile time, the compiler works out which one it's going to call, based on the compile time types of the arguments and the target of the method call. 
Category wise operators

           Now, things can get a little bit confusing sometimes when it comes to resolving overloads... especially as things can change between versions. This article will point out some of the things you might run into... but I'm not going to claim it's an authoritative guide to how overloading is performed. For that, read the specification - but be aware that you may get lost in a fairly complex topic. Overloading interacts with things like type inference and implicit conversions (including lambda expressions, anonymous methods and method groups, all of which can become tricky). All specification references are from the C# 4 specification.

This article is also not going to go into the design choices of when it's appropriate and when it's not. I'll give a little advice about when it might be potentially very confusing to use overloading, but anything beyond that will have to wait for another time. I will say that in general I believe overloading should be used for convenience, usually with all overloads ending up calling one "master" method. That's not always the case, but I believe it's the most common scenario which is appropriate.


In each example, I'll give a short program which will declare some methods and call one - and then I'll explain what gets called in which version of C#, and why. As I'm not trying to focus on the design decisions but merely the mechanical choices the C# compiler makes, I haven't tried to make the examples do anything realistic, or even given them realistic names: the overloaded method is always Foo, and it will always just print its own signature. Of course the action taken is irrelevant, but it makes it easier to grab the code and experiment with it if you want to.

Simple cases

Using System;
Class Test
{
    Static void Foo(int x)
    {
        Console.WriteLine("Foo(int x)");
    }
    Static void Foo(string y)
    {
        Console.WriteLine("Foo(string y)");
    }
    Static void Main()
    {
        Foo ("text");
    }
}
using System;
class Test
{
    static void Foo(int x)
    {
        Console.WriteLine("Foo(int x)");
    }
 static void Foo(double y)
    {
        Console.WriteLine("Foo(double y)");
    }
     static void Main()
    {
        Foo (10);
    }
}


operator Overloading Example

This time, Foo(int x) will be printed. Both methods are applicable - if we removed the method taking an `int`, the method taking a `double` would be called instead. The compiler decides which one to pick based on the better function member rules (section 7.5.3.2) which look at (amongst other things) what conversions are involved in going from each argument to the corresponding parameter type (int for the first method, double for the second). There are more rules (section 7.5.3.3) to say which conversion is better than the other - in this case, a conversion from an expression of type int to int is better than a conversion from int to double, so the first method "wins".

Multiple parameters

When there are multiple parameters involved, for one method to "beat" another one it has to be at least as good for each parameter, and better for at least one parameter. This is done on a method-by-method comparison: a method doesn't have to be better than all other methods for any single parameter. For example:
Difference between overloading and overriding

using System;

class Test
{
    static void Foo(int x, int y)
    {
        Console.WriteLine("Foo(int x, int y)");
    }

    static void Foo(int x, double y)
    {
        Console.WriteLine("Foo(int x, double y)");
    }

    static void Foo(double x, int y)
    {
        Console.WriteLine("Foo(double x, int y)");
    }
   
    static void Main()
    {
        Foo(5, 10);
    }

}


No comments:

Post a Comment