从接口集合中删除元素



我想使用此接口:

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);

这不会删除元素!我确实了解原因。原因是我的界面集合getter,再次如下:

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

ibars返回一个新列表,因此该元素已从返回的列表中删除,而不是从原始集合(bars(中删除。

我如何摆脱这种情况?我真的不想知道bar,而只想知道ibar。

Bars中的项目未删除,因为您正在 IBars的Getter中返回 new 列表:

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

您不能真正将ICollection<Bar>转换为ICollection<IBar>而不创建新内容,因为ICollection中的通用参数是不变的。

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

 void RemoveIBar(IBar ibar);

并在Foo中这样实现:

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

IBars的设置器中的检查是多余的。

显然,这不是类型的安全。这样做的更典型的安全是使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

最新更新