Nerdy tidbits from my life as a software engineer

Wednesday, January 7, 2009

Changing Return Types By Overriding Methods

The C# compiler will not allow you to do something like this:

public class A
{
    public object Test()
    {
        return new object();
    }

    public int Test()
    {
        return 0;
    }

}

error CS0111: Type 'A' already defines a member called 'Test' with the same parameter types

But if you really wanted to be able to do this sort of method overriding, you can actually accomplish it by using a bit of inheritance magic:

public class A
{
    public object Test()
    {
        return new object();
    }

}

public class B : A
{
    new public int Test()
    {
        return 0;
    }
}
B b = new B();
System.Diagnostics.Debug.WriteLine(b.Test());
System.Diagnostics.Debug.WriteLine(((A)b).Test());

outputs:
0
System.Object

I would imagine that this is probably a dangerous thing to do, and I wonder if there are any practical applications for consciously using it in your design.  A coworker of mine did something similar because he wanted to prevent clients from accessing a property of a base class that had a particularly attractive name.  But since that property was non-virtual (and returned a different type), he decided to hide it using the new keyword in the subclass.  So long as that property is referenced by its subclasses, this works fine.  And I suppose that if the property was virtual, life would be more problematic in another way, since he wouldn’t be able to change the type of of the property he was overloading.

Still, I’m not sure I like the fact that the C# compiler allows this design.  I suppose there’s no reason it can’t be legal, but I definitely think it’s something to be avoided as much as possible.

2 comments:

Jason Bock said...

IIRC you can do this in IL: override methods via a difference in return type only (as you need to specfify it in the call signature). But then you can't use those methods in C# or VB anyway.

Michael J. Braude said...

Yeah I think I remember reading that off a link on your blog. There are a lot of things you can get away with if you set the IL directly =).