For some reason I am battling to implement a property from a generic interface by using a generic base class as follows:
public interface IParent<TChild> where TChild : IChild
{
TChild Child { get; }
}
public interface IChild { }
Then I have a base class:
public class ParentBase<TChild> : IParent<TChild> where TChild : IChild
{
private TChild _child;
public ParentBase(TChild child)
{
this._child = child;
}
#region IParent<TChild> Members
public TChild Child
{
get { return _child; }
}
#endregion
}
Now I have a new Parent Derivative and Child object as follows:
public class MyChild : IChild { }
public class MyParent : ParentBase<MyChild>, IParent<IChild>
{
public MyParent(MyChild child)
: base(child)
{
}
}
I want to instantiate it and get the abstract (interface type) to pass to consumers as follows:
IParent<IChild> parent = new MyParent(new MyChild());
But for some reason I cannot implement the TChild correctly, even though I have defined the property public TChild Child
on the ParentBase, the compiler says it is not implemented, even if i try implement explicitly.
As you can see the constraints are all the way through to the base class.
You are deriving MyParent from ParentBase<MyChild>
and IParent<IChild>
. There is no implementation for
IParent<IChild> { IChild Child{get; } }
Adding an explicit implementation will allow your original code to compile
public class MyParent : ParentBase<MyChild>, IParent<IChild>
{
public MyParent(MyChild child)
: base(child)
{
}
#region Implementation of IParent<IChild>
IChild IParent<IChild>.Child
{
get { return base.Child; }
}
#endregion
}
If you also make IParent covariant like this:
public interface IParent<out TChild> where TChild : IChild
{
TChild Child { get; }
}
then you can now do this
IParent<IChild> parent = new MyParent(new MyChild());
or
ParentBase<MyChild> parent2 = new MyParent(new MyChild());
and
IParent<IChild> parent3 = parent2;
And as pointed out in the answer by @svick, with covariance you can then simplify by not deriving from IParent<IChild>
and removing the explicit interface implementation.
This is exactly where generic variance is useful. If you marked your IParent
interafce as covariant:
public interface IParent<out TChild> where TChild : IChild
and removed the explicit derivation of IParent<IChild>
from MyParent
:
public class MyParent : ParentBase<MyChild>
then MyParent
can be treated as if it implemented IParent<IChild>
. So for example, the following code would work:
MyParent parent = new MyParent(new MyChild());
IParent<IChild> iParent = parent;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With