我要使用此界面:
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。
答案 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
。