C# 将项目添加到列表中,但不生效

C# 将项目添加到列表中,但不生效,c#,list,getter,C#,List,Getter,在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 {

在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);
       }
    }
私有列表a;
公开名单EveryA
{
收到
{
如果(a==null)a=newlist();
返回a;
}
}
公共列表过滤器
{
收到
{
返回EveryA.FindAll(a=>a.IsInFilter);
}
}
现在我的问题是:语法如何
FilteredA.Add(this)
它编译并运行,但不能将任何项目添加到任何列表中。

更好的编译器应该通知(小)问题吗?

否。为什么要通知您?完全可以。
FilteredA
不返回
a
,而是返回
列表的新实例

FilteredA.Add(这个)
添加到此新实例

请参阅此代码:

var filteredA = FilteredA;
int count1 = filteredA.Count;
filteredA.Add(this);
int count2 = filteredA.Count;
Assert.AreEqual(count1 + 1, count2);

这表明新项目已添加到列表中。但是对于独立于类中的列表的新实例。

FindAll返回一个新列表。我想您正在将新项目添加到新列表中,但没有保留对新列表的引用。如果过滤列表来自方法而不是属性,则语义会更清晰。

它们不是同一个列表。这不是编译器可以为您检查的内容,因为编译器无法真正读懂您的心思。检查文档中的

结果是一个列表,但它不是同一个列表(怎么可能?您的原始列表没有被过滤!)

您应该能够将项目添加到
FilteredA
返回的列表中,除非它们不会显示在
a

我建议您改用LINQs
Where
,返回一个
IEnumerable
。这样,很明显,
FilteredA
的结果不应更改,只应迭代:

public IEnumerable<A> FilteredA
{
    get { return EveryA.Where(a => a.IsInFilter); }
}
public IEnumerable过滤器数据
{
获取{return EveryA.Where(a=>a.IsInFilter);}
}

公共列表过滤器数据
返回
FindAll
方法的一些输出,作为
列表
。这将不是与EveryA相同的对象,因此当它超出范围时,您添加的内容将丢失。

这不是真正的编译器问题-因为代码是有效的,所以可以正常编译。问题更多的是在代码质量级别上。要捕获类似的内容,您可以使用类似的工具来分析代码

这两种方法都可以看作是查询方法。不应将结果公开为列表,而应公开为IEnumerable或[]。如果要将项目添加到列表中,请使用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);
}
private List items=new List();
公共数字EveryA
{
获取{返回项;}
}
公共IEnumerable FilteredA
{
获取{return items.Where(item=>item.IsInFilter);}
}
公共无效附加项(项目)
{
项目。添加(项目);
}

我同意,FilteredA应该是一个方法/函数,而不是一个属性。为什么一个方法会产生更清晰的语义?并且-当属性返回IEnmerable而不是List时,您认为它是否仍然是一个方法(如果是,为什么)?属性意味着一些相当静态的东西;对于两个单独的调用,它应该总是返回相同的内容(当然,除非有人在两个调用之间写入了属性)。具有getter副作用的属性(与读取属性相关的属性除外,比如日志记录或延迟加载)令人困惑,就像在本例中,代码的作者您感到困惑一样。名为GetFilteredA()的方法看起来更像是能够通过每次调用创建新对象。是的,IEnumerable返回方法也应该是一种方法。详细说明一下:我在Google上搜索了方法和属性,第一个搜索结果是“一般来说,属性存储对象的数据,方法是可以要求对象执行的操作”。因此属性获取者专注于检索数据(基础列表),而对该成员的要求是执行一个操作(过滤列表)并返回结果。+1表示linq建议,如果可以的话,+1表示“编译器无法真正读懂您的想法”IEnumerable的建议是非常有用和优雅的,我必须记住这一点。但是,使用Linq的建议对我来说没有太大意义;我看不出我的示例代码中的谓词与“Linq”有什么区别,我只是指
System.Linq
中提供的扩展方法,即
Where
。与您的示例中的谓词没有区别,事实上,我重用了您的谓词。区别只是Linq版本使用了延迟求值。您仍然可以使用您的版本,只需更改返回类型。我只是从未想过当然……这是一个很好的解决方案。不过我还是有点喜欢公开名单EveryA,可能也是口味的问题吧?@phoog,我糟糕的、固定的答案。