views:

74

answers:

1

Given:

interface IFoo
{
    void Print(string text = "abc");
}

class Bar : IFoo
{
    public void Print(string text = "def")
    {
        Console.WriteLine(text);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Bar b = new Bar();
        b.Print();

        IFoo f = b as IFoo;
        f.Print();
    }
}

The output is:

def
abc

Is just me or this is a little odd? Initially I was expecting "def" in both cases. However, if that would be the case then the optional argument abstract methods would be useless. But still seems like a good starting point for nasty bugs.

+4  A: 

Optional parameters are a compiler feature, and the compiler can only work on type information that's available at compile time. Therefore the values are taken from the type of the reference you're operating on, not the actual run-time type. In this simple test case it would be possible to find out the actual type of f via static analysis, but that only rarely works in real-life examples and therefore isn't implemented.

Matti Virkkunen
This is correct. Also note that the interface or abstract method can have optional parameters and the derived method (the override) can omit it. In that case, `f.Print()` would compile but `b.Print()` would not.
Timwi
Although I need to add another nitpick: the reason it isn’t implemented is not because static analysis is hard, but because it’s not in the specification.
Timwi
@Timwi: Maybe it's not in the specification because it's hard. And it's not only hard, but impossible to do consistently, for example if you have multiple compilations units.
Matti Virkkunen
What is more it would be really confusing if this worked one way when static analysis was possible and another way when it was not.
Stilgar
@Matti: That’s right, it’s not in the spec because it’s *hard to write a spec for*, not because it’s hard to implement (implement what, without a spec?)
Timwi
@Timwi: No, it's not in the spec because it's *impossible to write a spec for* in a way that works consistently in all cases. The runtime type for something can't always be figured out at compile-time, and the cases in which it can't be done are rather common. And if you can't figure it out in all cases, it would be a very confusing feature to have.
Matti Virkkunen