列表在方法 C# 中不会更改

本文关键字:方法 列表 | 更新日期: 2023-09-27 18:29:45

我有一个类Items,我尝试对项目列表进行排序:

private static void Sort(List<Items> items)
{
.
.
.
   SortDesc(items);
}
private static void SortDesc(List<Items> items)
{
  items = items.OrderByDescending(x => x.Neto).ToList();
}

当调试器在 SortDesc() 中时,列表中的项按Neto DESC排序。当我继续并返回Sort()时,列表回到我打电话之前的状态SortDesc()

默认情况下,List<T>通过 ref 发送,那么为什么这不起作用呢?

谢谢!

列表在方法 C# 中不会更改

您正在使用以下代码行更改items指向的内存中的引用:

 items = items.OrderByDescending(x => x.Neto).ToList();

调用 SortDesc 方法时,列表对象通过引用传递。然后你正在创建新列表。在此之后,您将它设置为items参数。在此之后,items指向新的引用,而不是以前的引用。但是,真正的items仍然指向旧的。

因此,您必须返回新创建的列表:

private static List<Items> SortDesc(List<Items> items)
{
  return items.OrderByDescending(x => x.Neto).ToList();
}

然后,只需在Sort方法中设置它:

items = SortDesc(items);

PS:您也可以显式使用ref关键字来获得所需的结果,但这实际上不是首选方式。(...void SortDesc(ref List<Items> items)(。你可以从他对这个问题的回答中读到@JonSkeet答案 何时使用 ref 以及何时在 C# 中不需要:

有用的答案:你几乎不需要使用ref/out。它基本上是一个 获取另一个返回值的方式,通常应避免 正是因为这意味着该方法可能也在尝试这样做 多。

您需要退回订购的物品,

private static  List<Items>  SortFromTheHighPriceToLowPriceByNeto(List<Items> items)
{
    items = items.OrderByDescending(x => x.Neto).ToList();
    return items;
}

> 调用 SortDesc 时,会将对原始items变量的引用的副本传递给方法。因此,在重新分配item的方法中,您将新引用分配给原始引用的副本,而不是原始引用本身。原始引用保持不变。

为了更新原始引用,您需要通过引用传递items。这样做:

private static void SortDesc(ref List<Items> items)
{
    items = items.OrderByDescending(x => x.Neto).ToList();
}

如果您这样做,则呼叫将变为SortDesc(ref items)。这将按预期工作。

默认情况下,List<T>通过 ref 发送,那么为什么这不起作用呢?

否,所有未特别标记的参数都是按值传递的(它适用于引用类型和值类型(。如果您将方法更改为ref它将起作用:

private static void SortDesc(ref List<Items> items)
{
  items = items.OrderByDescending(x => x.Neto).ToList();
}

正如法哈德的回答中所解释的那样,这里的要点是.ToList()创造了一个新的List<Items>实例。旧实例保持不变。上面items = ...赋值会更改引用的值(从引用原始实例到引用新实例(,因此如果参数是按值计算的,它将不起作用。

由于您创建了一个新实例,因此最好直接返回它:

private static List<Items> SortDesc(List<Items> items)
{
  return items.OrderByDescending(x => x.Neto).ToList();
}

但是,既然您void方法,也许您想对同一列表进行排序而不是创建另一个列表?

在这种情况下,有一些可能性。一种是在List<>上使用Sort方法,像这样:

private static void SortDesc(List<Items> items)
{
  items.Sort((x, y) => y.Neto.CompareTo(x.Neto)); // unstable
}

或:

private static void SortDesc(List<Items> items)
{
  items.Sort((x, y) => Comparer<Xxx>.Default.Compare(y.Neto, x.Neto)); // unstable
}

其中Xxx表示Neto属性的声明(编译时(类型。如果.Neto从不为 null 引用(包括 Xxx 是值类型的情况(,则这两个中的第一个(更简单(工作正常。

这些是下降的,因为我们交换了 lambda 箭头之后的xy

警告:不稳定意味着如果List<>中的某些Items具有同样小的.Neto,则不知道它们的顺序会是什么。这等同于前面的稳定示例。

如果您需要 Linq OrderByDescending 或需要稳定排序,您可以尝试以下方法(尽管它并不漂亮(:

private static void SortDesc(List<Items> items)
{
  var tempList = items.OrderByDescending(x => x.Neto).ToList();
  items.Clear();
  items.AddRange(tempList);
}

除了 ClearAddRange之外,您还可以使用包含 items[i] = tempList[i]for 循环显式复制列表条目。