列表在排序时变为空

本文关键字:排序 列表 | 更新日期: 2023-09-27 18:30:38

>我有以下方法:

    public List<Vehicle> Vehicles
    {
        get { return _vehicles; }
    }

这将返回数据。如果我执行以下操作;

    public List<Vehicle> Vehicles
    {
        get { return _vehicles.OrderBy(v => v.Year).ToList(); }
    }

它变得空。如果我在此方法之外调用 orderby myList = vehicleList.Vehicles.OrderBy(x => x.Year)则列表将包含所有需要的数据。

我很困惑为什么。

列表在排序时变为空

在第一种情况下,您返回的是对该列表的引用,而不是列表的副本。 如果内部列表在以后修改,那么外部列表将能够观察到这些更改(因为它毕竟是同一个列表)。

当您从列表外部使用 LINQ 的 OrderBy 方法时,它将延迟执行。 直到您实际迭代该序列的结果,它才会查看列表;在这一点上很可能已经改变了。

当您在属性获取器中使用ToList时,您正在获取列表的副本,而不仅仅是复制对它的引用,因此它基本上是该时刻的快照。 在你得到属性的时候,列表[显然]是空的,但是当你迭代它时,它[显然]不是。

如果两者都具有延迟执行的能力很重要,并且此属性中的项始终基于调用方未手动应用的排序进行访问,则可以改用如下所示的内容:

public IEnumerable<Vehicle> Vehicles
{
    get { return _vehicles.OrderBy(v => v.Year); }
}

也就是说,如果在访问时始终对收藏进行排序很重要,那么最好只是将物品存储在已分类的庄园中,这样访问这些物品的成本就越便宜。 考虑改用类似SortedSet的东西而不是List

我认为你错过了一个事实,即ToList()创建新的List<T>而不是返回底层。

因此,当您致电:

var list = vehicleList.Vehicles;
list.Add(new Vehicle());
list.Add(new Vehicle());
Console.WriteLine(vehicleList.Vehicles.Count);

它将打印您的第一个Vehicles财产声明的2,并为第二个0

这是因为使用第二个属性声明时,您将项添加到刚刚使用ToList()调用创建的List,而不是从支持字段添加到该_vehicles

要使其正常工作,请尝试以下操作:

public List<Vehicle> Vehicles
{
    get { return (_vehicles = _vehicles.OrderBy(v => v.Year).ToList()); }
}

或者使用List<T>.Sort方法而不是OrderBy LINQ 扩展方法:

public List<Vehicle> Vehicles
{
    get
    {
        _vehicles.Sort((v1, v2) => v1.Year.CompareTo(v2.Year));
        return _vehicles;
    }
}

但要明确一点:你应该高度考虑,拥有这种财产的整体想法是错误的。您需要始终对数据进行排序吗?使用正确的数据结构,例如SortedList<int, Vehicle>,而不是每次触发属性 getter 时排序的标准List