在C#类中,我有一个列表和两个不同的getter用于列表:
private List<A> a;
public List<A> EveryA
{
get
{
if (a == null) a = new List<A>();
return a;
}
}
public List<A> FilteredA
{
get
{
return EveryA.FindAll(a => a.IsInFilter);
}
}
现在我的问题是:语法FilteredA.Add(this);
怎么样?
它编译并运行但不能将任何项目添加到任何列表中
一个更好的编译器是否必须通知(小)问题?
答案 0 :(得分:5)
他们不是同一个名单。这不是编译器可以为您检查的东西,因为编译器无法真正读懂您的想法。查看List<T>.FindAll
结果是一个列表,但它不是同一个列表(怎么可能?你的原始列表没有被过滤!)。
您应该能够将项目添加到FilteredA
返回的列表中,但它们不会显示在a
中。
我建议您使用LINQ Where
代替IEnumerable<T>
。这样,显然FilteredA
的结果不应该改变,只能迭代:
public IEnumerable<A> FilteredA
{
get { return EveryA.Where(a => a.IsInFilter); }
}
答案 1 :(得分:3)
没有。为什么要通知你这个?完全没问题
FilteredA
不会返回a
,而是List<A>
的新实例
FilteredA.Add(this);
将this
添加到此新实例。
请参阅此代码:
var filteredA = FilteredA;
int count1 = filteredA.Count;
filteredA.Add(this);
int count2 = filteredA.Count;
Assert.AreEqual(count1 + 1, count2);
这表明新项目已添加到列表中。但是对于那个与你班级里面的列表无关的新实例。
答案 2 :(得分:3)
FindAll返回一个新列表。您想将新项目添加到新列表中,但不保留对新列表的引用。如果过滤后的列表来自方法而不是属性,则语义会更清晰。
答案 3 :(得分:2)
public List<A> FilteredA
返回FindAll
方法的一些输出,作为List<A>
。这与EveryA
不同,因此当它超出范围时,您的添加将会丢失。
答案 4 :(得分:1)
这不是一个真正的编译器问题 - 因为代码有效它会编译得很好。问题更多的是代码质量水平。要捕获这样的内容,您可以使用FxCop之类的工具来分析代码。
这两种方法都可以看作是查询方法。您不应将结果公开为List,而应公开IEnumerable或A []。如果要将项目添加到列表中,请使用Add方法执行此操作。
private List<A> items = new List<A>();
public IEnumerable<A> EveryA
{
get { return items; }
}
public IEnumerable<A> FilteredA
{
get { return items.Where(item => item.IsInFilter); }
}
public void AddItem(A item)
{
items.Add(item);
}