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
How to Get the Index of the Highest Value in an Array Using Linq
Convert Am/Pm Time to 24 Hours Format
How to Delay Shutdown and Run a Process in Window Service
Unity - Checking If the Player Is Grounded Not Working
C# Datagridview Checkbox Checked Event
Entity Framework. Delete All Rows in Table
In C# Differencebetween a Destructor and a Finalize Method in a Class
Display Hourglass When Application Is Busy
Generic List - Moving an Item Within the List
Recommendations on Parsing .Eml Files in C#
How to Pass an Event to a Method
Pass a Value from One Form to Another
How to Get the Access Token from a Blazor (Server-Side) Web App
Auto Versioning in Visual Studio 2017 (.Net Core)
Event Signature in .Net -- Using a Strong Typed 'Sender'
Best Hashing Algorithm in Terms of Hash Collisions and Performance for Strings