given the following:
class A : B {}
interface I
{
B TheObject {get;set;}
}
can I do this somehow?
class C : I
{
public A TheObject {get;set;}
}
note the interface has the base class and the implementation has the sub class.
given the following:
class A : B {}
interface I
{
B TheObject {get;set;}
}
can I do this somehow?
class C : I
{
public A TheObject {get;set;}
}
note the interface has the base class and the implementation has the sub class.
Give this a try
class C : I
{
public A TheObject {get;set;}
B I.TheObject
{
get { return A; }
set { A = value as A; }
}
}
You may need to modify the B setter, depending on your needs. Implementing an interface this way has the following consequences. When dealing with a variable typed as a C you will not be able to access B TheObject. If you need to you will need to declare an I variable and assign it to your C var. Implementing I this way is known as an explicit implementation.
eg
C c = new C();
A a = c.TheObject; // TheObject is an A
I i = c;
B b = i.TheObject;
You can't do it because the return type of the interface implementation must match. But, my reasoning behind why you can't do it was wrong (as pointed out in the comments). You must match the signature, but you can return a new A from C ...
public class C : I
{
public B TheObject { get { return new A(); } set {} }
}
No, you can't. At least not without C# 4.0's Covariance/Contravariance feature.
Nope. The compiler will complain about the type mismatch.
Also, I'm going to disagree with Paul: I don't think variance will help in your case. Take a look at what Skeet has to say about variance here.
No, assume the following:
class D : B {}
C c = new C();
c.TheObject = new D(); // error. D is not A, A is not D
With the above class I can still use D
with objects implementing interface I
, but let's assume I want to set TheObject
property of an instance of C
to an instance of D
. I can't, because D
and A
are siblings. They both inherit from the same class and things would be OK as they are in the interface, but declaring that you expect an A
puzzles the compiler. An instance of A is not an instance of D, but instances of both A and D are instances of B.
This rule follows Liskov Substitution Principle.
P.S. I want to thank Troels Knak-Nielsen for opening my mind about this subtlety.
What you're thinking of is covariance/contravariance, but even with C# 4.0 this wouldn't work. It still needs to be useable if you only have a reference to the interface.
The getter would work, as A is also a B, but the setter wouldn't work, since the implementation expects an A, while the interface allows you to set TheObject to B. Generally, return values can be subtypes, and arguments can be base types with covariance/contravariance. But only in C# 4.0.
This compiles:
class B { }
class A : B { }
interface I<T> where T : B
{
T TheObject { get; set; }
}
class C : I<A>
{
public A TheObject { get; set; }
}
But I assume this is not what you want?