简体   繁体   English

在清单之间投放 <MyType> 和清单 <IMyType>

[英]Cast between List<MyType> and List<IMyType>

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. 我正在尝试解决问题及其前两个答案中所述的C#中对返回类型协方差缺乏支持的问题。 For the most part I'm not having any problems setting up the casts, but one property where I'm 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? 为了使IFoo.manyBars能够正常工作,我需要做什么?

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; 您将不得不using System.Linq;添加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> . 如果这不是您想要的,则应考虑使用另一种方法,例如使用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. 使用List<IBar>也意味着有人可能会尝试做anObject.manyBars.Remove(0) ,这将对存储在anObject的列表完全 anObject ,因为返回了副本。

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. 如果您可以投射该实例,那么当我尝试Add不是CBar的IBar时会发生什么。

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. 尽管请记住尽管对象相同,但是您将检索不同的列表,因此在添加/删除列表中的对象时需要格外小心。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM