请考虑以下代码段:
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 :(得分:1)
如上所述,在衡量与合理的替代方案之前,不要假设任何事情都是性能问题。也就是说,可能提高性能的一些选项是:
IEnumerable
而不是List
,以利用延迟执行。 (例如First
之类的操作会更快,因为你不需要为整个列表添加水合物)您必须确定性能改进是否值得额外维护。就个人而言,我会从一个更简单的解决方案开始,只有在改进证明风险和工作合理时才进行重构。
答案 1 :(得分: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等来仅对列表进行一次评估。
还有一个重复:没有分析的性能声明