Nathan Nau
Nathan Nau

Reputation: 83

Confusing overload resolution

I have a class that inherits from another class to allow using nullable value. But when I use it with non-nullable value​​, it uses the overload anyway for nullable.

I do not understand why the function of the class c2 mask the function of the class c1 in this code :

class c1
{
    public void fn1(int value)
    {
        Console.WriteLine("value {0} is normal", value);
    }
    public void fn1(int? value)
    {
        Console.WriteLine("value {0} is nullable", value);
    }
    public void fn2(int value)
    {
        Console.WriteLine("value {0} is normal", value);
    }
}
class c2: c1
{
    public void fn2(int? value)
    {
        Console.WriteLine("value {0} is nullable", value);
    }
}

class Program
{
    static void Main(string[] args)
    {
        c1 o1 = new c1();
        c2 o2 = new c2();
        int val = 10;
        o1.fn1(val);
        o2.fn1(val);
        o2.fn2(val);
        Console.ReadLine();
    }
}

And the result is :

value 10 is normal.
value 10 is normal.
value 10 is nullable.

However c2 has function fn2(int).

Upvotes: 3

Views: 107

Answers (4)

Nathan Nau
Nathan Nau

Reputation: 83

Like say Handoko.Chen, on Jon Skeet's blog we can find

The compiler ignores the overriding method in the child.

So the only way I found is to hide inherit method :

class c2: c1 {
    public void fn2(int? value) {
        Console.WriteLine("value {0} is nullable", value);
    }
    public new void fn2(int value) {
        base.fn2(value);
    }
}

Upvotes: 0

Dax Fohl
Dax Fohl

Reputation: 10781

As is true in many edge cases, there's no divined "why" to it, it's just how the C# spec was written. They could have done it other ways, but decided to do it this way. https://msdn.microsoft.com/en-us/library/aa691336(v=vs.71).aspx

Most relevant portion (from "7.4.2 Overload resolution" of C# spec linked above, different versions of spec may have similar text in other section):

the set of candidates for a method invocation does not include ... methods in a base class are not candidates if any method in a derived class is applicable

Upvotes: 2

Han
Han

Reputation: 3072

This is what I found on Jon Skeet's blog.

Inheritance can cause a confusing effect. When the compiler goes looking for instance method overloads, it considers the compile-time class of the "target" of the call, and looks at methods declared there. If it can't find anything suitable, it then looks at the parent class... then the grandparent class, etc. This means that if there are two methods at different levels of the hierarchy, the "deeper" one will be chosen first, even if it isn't a "better function member" for the call.

http://csharpindepth.com/Articles/General/Overloading.aspx

Upvotes: 2

Dweeberly
Dweeberly

Reputation: 4777

Resolution of your functions follows your class hierarchy. In the example you posted function c2::fn2 matches your call o2.fn2(val) because it has been explicitly defined in c2 and the compiler can implicitly covert int to int? In effect you have hidden c1::fn2.

You can look at making your c1 class abstract (sans implementation) or virtual with override in c2.

Upvotes: 0

Related Questions