从接口集合中删除元素

时间:2019-05-01 05:54:13

标签: c# collections interface

我要使用此界面:

public interface IFoo
{
 int Id { get; set; }
 string Name { get; set; }
 ICollection<IBar> IBars{ get; set; } //association with another entity
}

我的实现如下:

public class Foo : IFoo
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Bar> Bars{ get; set; }

//Interface implementation
 public ICollection<IBar> IBars
        {
            get
            {
                return Bars.Cast<IBar>().ToList();
                //or return new List<ICardInquiry>(CardsInquiries);
            }

            set
            {
                if (value is ICollection<IBar>)
                    Bars= ((ICollection<IBar>)value).Cast<Bar>().ToList();
                else
                    throw new NotImplementedException();
            }
        }
}

此实现阻止我从集合中删除元素:

IFoo iFoo = MyIFooFactory.CreateIFoo();
IBar iBar = iFooIBars.First();
iFoo.IBars.Remove(iBar);

这不会删除元素!我知道为什么。原因是我的接口集合获取器,再次如下:

public ICollection<IBar> IBars
        {
            get
            {
                return Bars.Cast<IBar>().ToList();
                //or return new List<ICardInquiry>(CardsInquiries);
            }
          ...
         }

IBars返回一个新列表,因此该元素将从返回列表中移除,而不是从原始集合(Bars)中移除。

如何摆脱这种情况? 我真的不希望IFoo知道Bar并且只操纵IBar。

1 个答案:

答案 0 :(得分:0)

Bars中的项目不会被删除,因为您正在IBars的getter中返回一个 new 列表:

return Bars.Cast<IBar>().ToList(); // ToList creates a new list.

由于ICollection<Bar>中的通用参数是不变的,因此如果不创建新内容,就无法将ICollection<IBar>转换为ICollection

您在这里唯一可以做的就是在Remove中添加一个IFoo方法:

 void RemoveIBar(IBar ibar);

并在Foo中实现它:

public void RemoveIBar(IBar ibar) {
    if (ibar is Bar) {
        Bars.Remove((Bar)ibar);
    } else {
        throw new NotImplementedException();
    }
}

此外,在IBars的setter中的检查是多余的。

显然,这不是类型安全的。执行此操作更安全的类型是使IFoo接受通用参数TBar并拥有一个ICollection<TBar>Foo然后可以实现IFoo<Bar>

public interface IFoo<TBar> where TBar: IBar
{
    int Id { get; set; }
    string Name { get; set; }
    ICollection<TBar> TBars{ get; set; } //association with another entity
}

public class Foo : IFoo<Bar>
{

    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Bar> Bars{ get; set; }

}

但是我想知道IFoo就算是Bar