views:

137

answers:

4

My subclasses don't appear to be able to masquerade as the base class when satisfying interface requirements. For example:

class MyBaseClass
{}

class MySubClass : MyBaseClass
{}

interface MyInterface
{
    MyBaseClass someFunction();
}

class MyImplementation : MyInterface
{
    public MySubClass someFunction() { return null; }
}

Generates the following error:

'MyNamespace.MyImplementation' does not implement interface member 'MyNamespace.MyInterface.someFunction()'. 'MyNamespace.MyImplementation.someFunction()' cannot implement 'MyNamespace.MyInterface.someFunction()' because it does not have the matching return type of 'MyNamespace.MyBaseClass'.

This is also a problem with requiring interfaces vs. implementations. For example, if I have an interface with a function that returns an IList my implementation cannot return a List - it MUST return an IList.

Am I doing something wrong or is this a limitation of C# interfaces?

A: 

MyImplementation is quite clearly not implementing that interface; a method that returns MySubClass is not the same as a method that returns MyBaseClass, regardless of whether they are related classes.

The same thing is true of your List/IList example, I can't understand why you would consider it a weakness.

Paul Creasey
Well any method that's expecting a MyBaseClass can take a MySubClass right? So the OP actually has a very valid point.
BFree
Well one of the major purposes of inheritance is type masquerading. Thus if I have a type A and a type B which inherits from A, I should be able to say:A thing = new B();etc.You can also do this with function overrides, i.e.A implements a function Bar which returns an A.B overrides function Bar with its own definition, which returns a B.This is fine.
Ender
I don't agree, interchangable they may be, but the same they are not.
Paul Creasey
+1  A: 

Signatures must match exactly, you must do:

class MyImplementation : MyInterface
{
    public MyBaseClass someFunction() { return null; }
}

You could implement generics though like this:

interface MyInterface<T>
{
    T someFunction();
}

class MyImplementation : MyInterface<MySubClass>
{
    public MySubClass someFunction() { return null; }
}

Note: I'm may be missing something syntax related, like MyInterface.someFunction

Aequitarum Custos
You can also use constraints to force T to be your base class. `where T : MyBaseClass`
unholysampler
+3  A: 

C# doesn't support covariant return types. When implementing an interface, you have to return the type specified by the interface. If you want to, you can explicitly implement the interface and have another method with the same name that returns the subtype. For example:

class MyImplementation : MyInterface
{
    MyBaseClass MyInterface.someFunction() { return null; }
    public MySubClass someFunction() { return null; }
}
Ben Lings
You could even get away with your explicit implementation being `return (MyBaseClass)someFunction();`
Anon.
Starting with .NET 4 it does
Sander Rijken
@Sander - I think .Net 4 supports covariance in generics, but not covariant return types.
Ben Lings
+1  A: 

If the interface expects MyBaseClass then you need to provide that type. You can down cast your MySubClass instance and cast it back when you retrieve it.

James