I'm trying to work around the lack of support for return type covariance in C# as described in this question and the first two answers to it. For the most part I'm not having any problems setting up the casts, but one property where I'开发者_如何学Gom using a list of objects/interfaces is stymieing my efforts.
What do I need to do in order to make the casts for IFoo.manyBars
work?
public interface IBar
{
}
public interface IFoo
{
IBar aBar { get; set; }
IEnumerable<IBar> manyBars { get; set; }
}
class CBar : IBar
{
}
class CFoo : IFoo
{
public CBar aBar { get; set; }
//this cast works
IBar IFoo.aBar
{
get { return aBar; }
set { aBar = (CBar)value; }
}
public List<CBar> manyBars { get; set; }
//the compiler can't cast either of these
List<IBar> IFoo.manyBars
{
get { return (List<IBar>)manyBars; }
set { manyBars = (List<CBar>)value; }
}
}
Try this. You will have to add using System.Linq;
to the top of the source file, if it's not there already.
List<IBar> IFoo.manyBars
{
get { return manyBars.Cast<IBar>().ToList(); }
set { manyBars = value.Cast<CBar>().ToList(); }
}
Note that this will allocate and copy a new array on each access to the property. If this is not what you want, you should consider an alternative approach, such as exposing the property using the type IEnumerable<IBar>
.
Using List<IBar>
also means someone might try to do anObject.manyBars.Remove(0)
which will do absolutely nothing to the list stored in anObject
, since a copy is returned.
You can make a copy:
get { return manyBars.OfType<IBar>().ToList(); }
set { manyBars = value.Cast<CBar>().ToList(); }
but you can't cast that instance. If you could cast that instance, what happens when I try to Add
an IBar that is not a CBar.
Depending on your needs, you could create a new list for returning:
return new List<IBar>(manyBars);
Although remember that although the objects will be the same, you will be retrieving a different list, so you'll need to be careful about adding/removing objects from the list.
精彩评论