2010-11-15 41 views
2

我试图解决在C#中返回类型协方差的支持不足的问题,如this问题及其前两个答案中所述。大多数情况下,我在设置演员时没有任何问题,但是使用对象/接口列表的一个属性妨碍了我的努力。之间的列表<MyType>和列表之间施展<IMyType>

我需要做什么才能使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; } 
    } 
} 

回答

3

试试这个。如果不存在,您必须将using System.Linq;添加到源文件的顶部。

List<IBar> IFoo.manyBars 
{ 
    get { return manyBars.Cast<IBar>().ToList(); } 
    set { manyBars = value.Cast<CBar>().ToList(); } 
} 

注意,这将分配并复制上一个新的阵列中的每个接入的财产。如果这不是你想要的,你应该考虑一种替代方法,例如使用类型IEnumerable<IBar>公开财产。

使用List<IBar>也意味着有人可能会尝试做anObject.manyBars.Remove(0)这将做绝对没有存储在anObject列表中,因为返回一个副本。

+0

将我的界面切换到IEnumerable 不是问题,这样做会避免使用Linq来执行强制转换结果的问题。 – 2010-11-15 21:06:17

+0

- 类的用户将无法删除项目,因为'IEnumerable '接口暴露无删除机制。所以对用户而言,它会*不会令人惊讶,因为他们甚至不能*尝试*删除项目。 – cdhowie 2010-11-15 21:12:38

+0

我想我可以忍受,因为IFoo/IBar消费者就是我想要封装的东西,并且向接口添加/删除方法似乎不会造成任何主要问题。 CFoo和COtherFoo应用程序的其余部分可以继续使用列表 /列表版本。 – 2010-11-15 21:22:31

0

根据您的需求,您可以返回创建一个新的列表:

return new List<IBar>(manyBars); 

虽然记得,虽然对象是相同的,你会获取不同的列表,让你”我们需要小心添加/删除列表中的对象。

+0

不幸的是,我的IFoo消费者需要能够从列表中添加/删除,因此创建新副本不是一个可行的选项。 – 2010-11-15 21:10:43

+0

好的,但要小心,因为其他答案有同样的问题。你可以将列表声明更改为“public List manyBars {get; set;}”? – 2010-11-15 21:24:18

+0

CBar和COtherBar都包含一些不共享的IBar用户不关心的方法/属性,所以我无法将CFoo/COtherFoo的定义更改为使用列表,而无需添加将所有使用CFoo/COtherFoo对象的代码库的(更大)部分进行转换。 – 2010-11-15 21:41:47

2

您可以复制:

get { return manyBars.OfType<IBar>().ToList(); } 
set { manyBars = value.Cast<CBar>().ToList(); } 

,但你不能施放该实例。如果你可以投射那个实例,当我尝试Add一个不是CBar的IBar时会发生什么。

+0

我知道这有些脆弱,但实际上CFoo/CBar和COtherFoo/COtherBar的用户将被隔离。使用后者为相关项目共享前者编写的一段代码是最后一刻的需求变更,因此我在寻求优雅方面受限于我的重构范围。 – 2010-11-15 21:09:45

+0

好的,如果你想在出现问题时抛出Cast,请使用Cast。如果您想要过滤掉无效项目,请使用OfType。这几乎是你唯一的选择。 – 2010-11-15 22:12:48