C# LINQ在属性Getter中-性能差?

C# LINQ在属性Getter中-性能差?,c#,performance,linq,design-patterns,C#,Performance,Linq,Design Patterns,考虑以下代码段: private List<object> MyList; public List<object> SubSetOfList { get { return MyList.Where(p => p.Property == SomeValue).ToList(); } } 私有列表MyList; 公开名单 { get{return MyList.Where(p=>p.Property==SomeValu

考虑以下代码段:

    private List<object> MyList;

    public List<object> SubSetOfList
    {
        get { return MyList.Where(p => p.Property == SomeValue).ToList(); }
    }
私有列表MyList;
公开名单
{
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);
    }
private List\u myList;
公共列表完整列表
{
获取{return\u myList;}
}
私人资产评估师;
公众价值论者
{
获取{return\u valuelist;}
}
私人名单(估价员),;
公开资产评估师
{
获取{return\u valueBList;}
}
公共无效附加项(对象obj)
{
_myList.Add(obj);
if(obj.someproperty==valueA)
_价值论者。添加(obj);
if(obj.someproperty==valueB)
_价值列表添加(obj);
}
是否有一个或多个普遍接受的模式来处理这种行为?

如前所述,在您根据合理的替代方案进行衡量之前,不要认为任何事情都是性能问题。也就是说,可以提高性能的一些选项包括:

  • 将列表显示为
    IEnumerable
    s而不是
    List
    s,以利用延迟执行。(例如,像
    First
    这样的操作会更快,因为您不需要添加整个列表)
  • 缓存筛选的列表(如果添加了新项目或更改了影响列表的属性,请确保清除缓存)
  • 使用字典改进按属性查找(在添加项或更改属性时再次维护字典)
  • 按照您的建议维护单独的列表

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

    这完全取决于您的需求。如果您有某种存储需求,那么第二个解决方案的扩展性确实会很差。 如果您有性能要求,那么总是创建一个列表也可能会严重扩展

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

    private List<object> MyList;
    
    private List<object> _subList;
    public List<object> SubSetOfList
    {
        get { return _subList ?? (_subList = MyList.Where(p => p.Property == SomeValue).ToList();) }
    }
    
    私有列表MyList;
    私有列表_子列表;
    公开名单
    {
    获取{return{u subList???({u subList=MyList.Where(p=>p.Property==SomeValue.ToList();)}
    }
    
    这是一种懒惰的评估,因为它只做了一次。当然,您需要自己处理一致性,因为更改MyList需要使存储的子列表无效

    另一种解决方案是返回一个惰性计算的
    IEnumerable
    。但是请记住,这种类型的每个用户都需要反复地重新评估它。如果您的操作包含许多
    First()
    Last()
    等,那么这将更快,因为之前没有人评估过整个列表,如(@D Stanley提到的)

    但请注意,人们往往会对IEnumerables进行多次评估,最终导致性能损失。e、 g调用Any(),然后调用
    IEnumerable
    。然后调用者应该正确地使用ToList等对列表进行一次评估


    还有一个重复:没有评测就没有性能声明

    “但是,我认为它在性能方面可能无法很好地扩展。”-我认为,在删除复杂问题的可读解决方案之前,您应该真正分析应用程序,看看这是否真的是一个问题。了解您正在使用的LINQ提供程序(例如对象、实体框架)以及您希望访问此属性的频率将非常有用。通常,您可以通过缓存ToList的结果并在后续调用时返回缓存的版本来缓解此方法的任何性能问题。最好不要使用
    ToList
    执行查询,即使在
    SubSetOfList
    中使用固定值也是如此。你也不应该将房产用于“昂贵”的东西。然后用一个带参数的方法来代替。为了清楚起见,对“不要在没有分析的情况下声称性能差”的反复提及做出回应-我没有。这是一个关于这个问题的问题。我想知道是否有一个我不知道的可接受的解决方案。您当然需要自己处理一致性。您可以使用
    ObservableCollection
    来处理
    MyList
    而不是
    List
    ,并在
    CollectionChanged
    事件处理程序中将
    \u子列表设置为
    null
    。因此,这是一项简单的任务。