2014-04-02 30 views
0

考虑下面的代码片段:属性中的LINQ Getter - 性能差?

private List<object> MyList; 

    public List<object> SubSetOfList 
    { 
     get { return MyList.Where(p => p.Property == SomeValue).ToList(); } 
    } 

这是访问的子集,我感兴趣的列表的一个非常方便的方式。然而,我想它可能不会在性能方面扩展这么好。

我考虑的另一种模式如下。我不在乎这个,但是因为随着我感兴趣的子集数量的增加,它在复杂度方面出现了扩展问题。

private List<object> _myList; 
    public List<object> WholeList 
    { 
     get { return _myList; } 
    } 

    private List<object> _valueAList; 
    public List<object> ValueAList 
    { 
     get { return _valueAList; } 
    } 

    private List<object> _valueBList; 
    public List<object> ValueBList 
    { 
     get { return _valueBList; } 
    } 

    public void AddItem(object obj) 
    { 
     _myList.Add(obj); 

     if (obj.SomePropety == valueA) 
      _valueAList.Add(obj); 
     if (obj.SomePropety == valueB) 
      _valueBList.Add(obj); 
    } 

是否有普遍接受的模式或模式来处理这种行为?

+0

无性能要求“不过,我想这可能不会在性能方面扩展这么好。” - 我认为你应该真正地分析你的应用程序,看看在真正的问题之前放弃可读解决方案的复杂性。 – Jens

+0

了解您正在使用的LINQ提供程序(例如对象,实体框架)以及您期望访问此属性的频率会很有用。通常,通过缓存ToList的结果并在随后的调用中返回缓存版本,您可以缓解此方法的任何性能问题。 –

+1

即使在SubSetOfList中有一个固定值,也可以不用'ToList'执行查询。你也不应该将财产用于“昂贵”的东西。然后使用带有参数的方法。 –

回答

1

这完全取决于您的要求。如果你有某种存储需求,你的第二个解决方案确实会严重缩小。 如果您的性能要求比创建列表的时间长,可能也会严重缩放。

一个可能的解决方案是使用您的第一个解决方案,但存储结果列表并仅在访问时创建它,例如,

private List<object> MyList; 

private List<object> _subList; 
public List<object> SubSetOfList 
{ 
    get { return _subList ?? (_subList = MyList.Where(p => p.Property == SomeValue).ToList();) } 
} 

这是一种懒惰的评价,因为它是一次完成。您当然需要自己处理一致性,因为更改MyList将需要使存储的子列表无效。

另一种解决方案是返回延迟评估的IEnumerable<object>。但请记住,这种类型的每个用户都需要反复评估。如果你的操作包含很多First(),Last()等,那么实际上这会更快,因为之前从来没有人评估过整个列表,就像(@D Stanley所提到的)。

但请注意,人们有时会不止一次地评估IEnumerables导致明确的性能损失。例如调用Any(),然后调用IEnumerable。然后调用者应该正确使用ToList等来评估列表一次。

,也是一个重复:没有剖析

+1

*您当然需要自己处理一致性*您可以在'MyList'中使用'ObservableCollection '而不是'List ',并在'CollectionChanged'事件处理程序中将'_subList'设置为'null'。所以,这是一件容易的事。 – sloth

1

如上所述,不要假设什么是性能问题,直到你测量它对一个合理的选择。这就是说,一些可能提高性能的选项有:

  1. 揭列为IEnumerable!而非List s到采取延迟执行的优势。 (例如,像First这样的操作会更快,因为您不需要水合整个列表)
  2. 缓存已过滤的列表(如果添加了新项目或者更改了属性,会影响列表,请务必清除缓存)
  3. 使用字典来改善按属性查找(再次为添加项或添加属性更改主题词典)
  4. 维护单独的列表,如您所建议的。

您必须决定性能改进是否值得额外维护。就我个人而言,我会从一个更简单的解决方案开始,只有在改进证明风险和工作有效时才进行重构。