Linq OrderBy不对List<;T>;.如何对列表进行排序

本文关键字:排序 列表 不对 OrderBy List lt Linq gt | 更新日期: 2023-09-27 17:54:45

OrderBy子句出现问题,对排序没有任何影响。我在调试器中仔细检查了这一点,并确保这是一种代码的排序行被击中的情况,并在它之后查看结果,没有应用OrderBy。

public static IEnumerable<DDLOptions<TValueType>> GetDDLOptionsViewModel<TClass, TValueType>(
            IEnumerable<TClass> list, 
            Func<TClass, TValueType> value, 
            Func<TClass, string> displayText,
            bool sort = true
        )
        {
            List<DDLOptions<TValueType>> ddlOptions;
            ddlOptions = list.Select(
                l => new DDLOptions<TValueType>
                        {
                            Value = value(l),
                            DisplayText = displayText(l)
                        }
                    ).ToList();  <========== Works if I put the Order By here.
            if (sort)
            {
                ddlOptions.OrderBy(l => l.DisplayText); <===== Does NOT work here.
            }
            return ddlOptions;
        }

Linq OrderBy不对List<;T>;.如何对列表进行排序

OrderBy返回一个执行排序的查询:它不会修改原始列表(而类似List<T>.Sort的东西会修改原始列表(

相反,可以尝试以下方法:

ddlOptions = ddlOptions.OrderBy(l => l.DisplayText).ToList();

您可能想考虑ddlOptions的类型,或者在我们进行额外的ToList时在哪里/如何返回数据,但无论如何,这可能是本例的一个小问题。

请注意,这同样适用于其他LINQ函数,如GroupBy、Distinct、Concat-所有函数都返回结果,而不是修改源集合。

尝试:

if (sort)
{
    ddlOptions = ddlOptions.OrderBy(l => l.DisplayText); <===== Should work now.
}

正如其他人所说,你需要将OrderBy的结果分配给某个东西,因为它不会改变它所作用的序列。最简单的方法是将ddlOptions设置为IEnumerable而不是List,这样你就可以将结果分配给它。选择上的ToList调用也不需要:

public static IEnumerable<DDLOptions<TValueType>> GetDDLOptionsViewModel<TClass, TValueType>(
        IEnumerable<TClass> list,
        Func<TClass, TValueType> value,
        Func<TClass, string> displayText,
        bool sort = true
    )
{
    IEnumerable<DDLOptions<TValueType>> ddlOptions;
    ddlOptions = list.Select(
        l => new DDLOptions<TValueType>
                {
                    Value = value(l),
                    DisplayText = displayText(l)
                }
            );
    if (sort)
    {
        ddlOptions = ddlOptions.OrderBy(l => l.DisplayText);
    }
    return ddlOptions;
}

请注意,此版本的方法将使用延迟执行,因此在迭代序列之前不会实际执行Select/OrderBy。如果您不想这样做,可以在return行中添加ToList

您需要键入:

ddlOptions = ddlOptions.OrderBy(l => l.DisplayText);

OrderBy不对List<T>或任何其他IEnumerable<T>进行排序。它生成一个新的、排序的IEnumerable<T>。因此调用ddlOptions.OrderBy(...)不会修改ddlOptions

如果您有一个List<T>并希望对其进行排序,则可以使用Sort方法,特别是将Comparison<T>作为参数的重载。这实际上是对列表进行排序,而不是返回一个新的IEnumerable

Comparison<T>是代表一个函数的委托,该函数取T中的两个,如果第一个"小于"第二个,则返回负数;如果第一个比第二个"大",则返回正数;如果一个没有在另一个之前或之后排序,则返回零。

在这种情况下,你不必记住这一点。相反,你可以这样做:

ddlOptions.Sort((x, y) => string.CompareOrdinal(x.DisplayText, y.DisplayText));

您正在传递一个函数,该函数接受列表中的两个项,并返回它们的DisplayText属性的比较结果,这些属性将是负数、0或正数。

有时我们使用OrderBy,因为不会修改原始列表。但是,如果修改列表是我们想要的,那么我们可以使用Sort