Reputation: 45
Lets assume I've got a class Called StreetModel
that implements an interface called IStreetModel
:
public class StreetModel: IStreetModel {
// Properties go here
}
Said IStreetModel looks like so:
public interface IStreetModel {
// Properties go here
}
Now, say I have another interface called ILocationModel
that contains a property of type IStreetModel
:
public interface ILocationModel {
IStreetModel Street { get; }
}
And this ILocationModel
interface is implemented by a class called LocationModel
:
public class LocationModel: ILocationModel {
public StreetModel Street { get; } // This is where my query is
}
My Question: Within LocationModel
, why can't I implement StreetModel
even though it implements IStreetModel
. Why does the compiler want IStreetModel
specifically? It's confusing for me because in almost every other scenario within my program (except for collections) I can interchange usage of the two. Why not here?
Error Message:
'LocationModel' does not implement interface member 'ILocationModel.Street'. 'LocationModel.Street' cannot implement 'ILocationModel.Street' because it does not have the matching return type of 'IStreetModel'.
Upvotes: 1
Views: 580
Reputation: 109802
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;
}
Upvotes: 5