【问题标题】:Remove an element from an interface collection从接口集合中移除一个元素
【发布时间】:2019-05-01 05:54:13
【问题描述】:

我要使用这个界面:

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) 中删除。

我怎样才能摆脱这种情况? 我真的不想让 IFoo 知道 Bar 并且只操纵 IBar。

【问题讨论】:

  • 任何理由Bars 不能只是ICollection&lt;IBar&gt;
  • @Loocid : Bar 和 Foo 是实体框架模型类。如果我将 IBars 声明为 ICollection 而不是 ICollection,EF 将不会根据数据库人口设置我的导航属性。

标签: c# collections interface


【解决方案1】:

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

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

你不能真正将ICollection&lt;Bar&gt; 转换为ICollection&lt;IBar&gt; 而不创建新的东西,因为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 的 setter 中的检查也是多余的。

显然,这不是类型安全的。更安全的做法是让IFoo 采用泛型参数TBar 并拥有ICollection&lt;TBar&gt;。然后Foo可以实现IFoo&lt;Bar&gt;

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-06
    • 1970-01-01
    • 2020-11-06
    • 1970-01-01
    相关资源
    最近更新 更多