【问题标题】:List<int[]> is populated only by last contents of int[]List<int[]> 仅由 int[] 的最后内容填充
【发布时间】:2018-03-07 10:25:16
【问题描述】:

我正在测试如何从一个函数返回多个数据。我试图使用int[] 的列表。为此,我有一个返回List&lt;int[]&gt; 的函数,如下所示:

private List<int[]> Test()
{
        List<int[]> testlist = new List<int[]>();
        int[] record = new int[3];
        record[0] = 1;
        record[1] = 2;
        record[2] = 3;
        testlist.Add(record);
        record[0] = 11;
        record[1] = 12;
        record[2] = 13;
        testlist.Add(record);
        return testlist;
}

当我检查列表的内容时,我看到它包含 2 条记录,但它们都包含 int[] 的最后一条记录。这意味着,而不是

list[0] = {1,2,3}
list[1] = {11,12,13}

我明白了

list[0] = {11,12,13}
list[1] = {11,12,13}

我想知道为什么会这样。

【问题讨论】:

  • 数组是引用类型。您将相同的引用两次添加到列表中,然后修改它。您必须改为创建一个新数组。
  • 您正在向两个元素添加相同的数组。为每个元素创建一个新数组。
  • 你需要在testlist.Add(record);之后做record = new int[3];
  • 您需要在添加第一条记录后创建另一个数组。即在第一个 testlist.Add(record) 之后再次添加这一行 record = new int[3];
  • 感谢大家非常快速和准确的回复!进一步阅读链接也非常有用

标签: c# list int


【解决方案1】:

问题是您只有一个 int[] record 实例,您将其两次放入列表中。数组是reference type。文档指出:

使用引用类型,两个变量可以引用同一个对象;因此,对一个变量的操作会影响另一个变量引用的对象。

在第二次运行中,您会覆盖第一次运行的值,因为record 仍然指向同一个对象。这就是为什么两个数组中的值相同的原因。

要解决它,您需要为列表中的每个条目创建一个全新的实例:

 private List<int[]> Test()
{
    List<int[]> testlist = new List<int[]>();
    int[] record = new int[3];
    record[0] = 1;
    record[1] = 2;
    record[2] = 3;
    testlist.Add(record);

    int[] record2 = new int[3];
    record2[0] = 11;
    record2[1] = 12;
    record2[2] = 13;
    testlist.Add(record2);
    return testlist;
}

有关引用和值类型的更多信息,请阅读this article

【讨论】:

    【解决方案2】:

    数组,例如int[] 是引用类型。 因此,当您将 11 分配给数组的第一个单元格时,您将覆盖原来在该单元格中的 1。因为您的 List&lt;int[]&gt; 仅包含对数组的引用,所以值也在那里更改。

    相反,将数组的副本分配给列表以破坏这些引用:

    List<int[]> testlist = new List<int[]>();
    
    int[] record = new int[3];
    record[0] = 1;
    record[1] = 2;
    record[2] = 3;
    testlist.Add(record.ToArray()); // LINQ ToArray will create a copy
    
    record[0] = 11;
    record[1] = 12;
    record[2] = 13;
    testlist.Add(record.ToArray()); // LINQ ToArray will create a copy
    
    return testlist;
    

    或者不要重复使用同一个数组:

    List<int[]> testlist = new List<int[]>();
    int[] record1 = new int[3];
    record1[0] = 1;
    record1[1] = 2;
    record1[2] = 3;
    testlist.Add(record1);
    
    int[] record2 = new int[3];
    record2[0] = 11;
    record2[1] = 12;
    record2[2] = 13;
    testlist.Add(record2);
    
    return testlist;
    

    延伸阅读:Difference between a Value Type and a Reference Type

    【讨论】:

      【解决方案3】:

      testlist.Add(record) 正在向record 添加一个引用testlist 数组。

      换句话说,您不会向testlist 添加两个单独的数组;您要添加对同一数组 record 的引用两次。

      这意味着,如果您在将record 添加到列表后修改它,它也会在列表内更新。 testlist 不包含“实际数组”,它包含一个指向数组的指针。在这种情况下,该指针指向record

      你可以通过引入一个新数组来解决这个问题:

       private List<int[]> Test()
      {
              List<int[]> testlist = new List<int[]>();
              int[] record = new int[3];
              record[0] = 1;
              record[1] = 2;
              record[2] = 3;
              testlist.Add(record);
              int[] record2 = new int[3];
              record2[0] = 11;
              record2[1] = 12;
              record2[2] = 13;
              testlist.Add(record2);
              return testlist;
      }
      

      那么您的列表包含两个不同的对象,而不是对同一个对象的两个引用。

      要了解更多信息,您应该谷歌并阅读pass-by-referencepass-by-value。 C# 对大多数函数参数使用传递引用,但值得注意的例外是基本数字类型(例如 intfloat)和结构。

      【讨论】:

      • @MongZhu 哎呀,我修改了答案。
      【解决方案4】:

      因为您已覆盖引用并将其添加到列表中。如果您将值分配给新的参考,那么您可以获得您想要的。

      试试这个

       private List<int[]> Test()
      {
              List<int[]> testlist = new List<int[]>();
              int[] record = new int[3];
              record[0] = 1;
              record[1] = 2;
              record[2] = 3;
              testlist.Add(record);
              record = new int[3];// create new reference
              record[0] = 11;
              record[1] = 12;
              record[2] = 13;
              testlist.Add(record);
              return testlist;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-26
        • 2022-01-17
        • 1970-01-01
        • 2012-05-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多