"Interface Not Implemented" When Returning Derived Type

Interface not implemented when Returning Derived Type

Unfortunately, the return type must match. What you are looking for is called 'return type covariance' and C# doesn't support that.

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=90909

Eric Lippert, senior developer on C# Compiler team, mentions on his blog that they don't plan to support return type covariance.

"That kind of variance is called
"return type covariance". As I
mentioned early on in this series, (a)
this series is not about that kind of
variance, and (b) we have no plans to
implement that kind of variance in C#.
"

http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx

It's worth reading Eric's articles on covariance and contravariance.

http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx

Cannot implement interface member using derived type

The answer to your actual question ("why doesn't it compile?") is: The c# language requires that a return type for an implemented interface member matches exactly. That's the way the language was designed.

This was fixed by c# 9 in some cases, but not for interface implementations. See the section following The remainder of the draft specification below proposes a further extension to covariant returns of interface methods to be considered later in this documentation.

In the meantime, a possible workaround is to make your ILocationModel generic like so:

public interface IStreetModel
{
// Properties go here
}

public interface ILocationModel<out T> where T: IStreetModel
{
T Street { get; }
}

public class StreetModel : IStreetModel
{
// Properties go here
}

public class LocationModel : ILocationModel<StreetModel>
{
public StreetModel Street { get; } // This is where my query is
}

Of course the most obvious solution is simply to declare the return type of LocationModel.Street as IStreetModel.

Another alternative is to use explicit interface implementation, like so:

public class LocationModel : ILocationModel
{
public StreetModel Street { get; } // This is where my query is

IStreetModel ILocationModel.Street => Street;
}

Overriding interface method return type with derived class in implementation

Use Generics

interface IFactory<T> where T: BaseCar
{
T GetCar();
}

class MyFactory : IFactory<MyCar>
{
MyCar GetCar()
{
}
}

class MyCar : BaseCar
{

}

How can I return a more derived type from an interface?

Please try the following code, it should work like charm. Replace the Methods/Exception to your own implementation.

  public interface ITransformable<T, out S> where S : ITransformable<T, S>
{
S Slice(int x, int y, int width, int height);
S Slice(Rectangle value);
S Transpose();
S Flip(bool horizontal, bool vertical);
S Rotate(bool clockwise);
}

public class Mesh<T, S> : ITransformable<T, S> where S : Mesh<T,S>, ITransformable<T, S>, new()
{
public S Slice(int x, int y, int width, int height)
{
throw new NotImplementedException();
}

public S Slice(Rectangle value)
{
throw new NotImplementedException();
}

public S Transpose()
{
//The following will work smoothly.
S sObject = this.Slice(10, 20, 30, 40);
return sObject;
}
public S Flip(bool horizontal, bool vertical)
{
throw new NotImplementedException();
}

public S Rotate(bool clockwise)
{
throw new NotImplementedException();
}

}

public class Heightmap : Mesh<float, Heightmap>
{

}

public class Program
{
static void Main()
{
Heightmap heightmap = new Heightmap();
Heightmap map2 = heightmap.Transpose(); //This will work smoothly.
}
}

Do I need to define a same Interface in a derived class after define it in a base class?

Well, you may need to do it; here is a possible scenario:

When cloning, we usually want to return not universal object by cloned object type:

class Base {
// We can't declare this method as virtual: Derived class will return Derived
public Base Clone() {
...
}
}

...

Base test = new Base();

Base duplicate = test.Clone();

If we want to implement IClonable we have to do it explictly (in order to solve Clone() names conflict):

class Base : ICloneable {
public Base Clone() {
...
}

// This method is efficiently private, and that's why can't be virtual
object ICloneable.Clone() => Clone();
}

Now we want a Derived class which can be cloned as well:

class Derived : Base {
// Note that now we have new Clone method which returns Derived instance (not Base one)
public new Derived Clone() {
...
}
}

...

Derived test = new Derived();

Derived duplicate = test.Clone();

If we keep it like this then we'll have wrong behaviour:

 Derived test = new Derived();

// This will be wrong:
// Base.ICloneable.Clone() will be called which executes "Base Clone()" method
// instead of expected "new Derived Clone()"
object clone = (test as IClonable).Clone();

So we have to reimplement IClonable interface:

class Derived : Base, ICloneable {
// Please, note that now we have new Clone method which returns Derived instance
public new Derived Clone() {
...
}

// This ICloneable implementation will call Derived Clone()
object ICloneable.Clone() => Clone();
}

...

// Derived ICloneable.Clone() will be called
// which executes "new Derived Clone()" method
object clone = (test as IClonable).Clone();

C# interface method declared in Base class need not be again implemented in Derived class

Although I can't speak for the language team, you can answer this question by posing the alternative solution.

You want to know why B is considered to implement the interface IA even though the required method definition is in base class A, which doesn't implement the interface. So, let's consider the opposite: B should not be considered to implement the interface because the base class' method wasn't written with that interface in mind.

This means that your code doesn't compile. Why doesn't it compile? Because B doesn't implement required member Display of interface IA.

To fix this, you'd add a method Display to class B. That fixes the interface implementation. However, you now have a new compilation problem: you'll see a warning "B.Display()' hides inherited member 'ConsoleApplication1.A.Display()'. Use the new keyword if hiding was intended."

This is because your A.Display wasn't overrideable - and you don't want to override it. You can implement a method to call base.Display() if you choose, but this is extra code to essentially do nothing, and it makes a mess of your inheritance since a new method is handled differently to an override. (If you write A x = new B(); x.Display(); then you'll actually call A.Display() directly, which could get messy as your code evolves and is an accident waiting to happen.)

Alternatively, you might implement an entirely new B.Display method. What you've also now done is hidden the method implemented in class A from anyone who might derive from B or create an instance of B. Using new to hide methods is rarely a recipe for an understandable object structure, and this would be no exception - all so that you can implement an interface cleanly.

So ultimately, I would imagine, this decision was made because the alternative is far too messy.



Related Topics



Leave a reply



Submit