【问题标题】:resize an array in the method in c#在 C# 的方法中调整数组的大小
【发布时间】:2021-04-30 10:45:51
【问题描述】:

请认为我们有一个名为 AddArr 的方法,它接受一个数组和几个值并将这些值添加到数组中。

喜欢这个

c#代码

    public static void AddArr(string[] nums, params string[] n)
    {
        string[] l = new string[nums.Length + n.Length];
        int j;
        for (j = 0; j < nums.Length; j++)
        {
            l[j] = nums[j];
        }
        for (int h = 0; h < n.Length; h++, j++)
        {
            l[j] = n[h];
        }
        Array.Resize(ref nums, l.Length);
        for (int f = 0; f < nums.Length; f++)
        {
            nums[f] = l[f];
        }
    }

但对于第 13 行

Array.Resize(ref nums, l.Length);

它只调整 string[]nums 方法的入口参数的大小,而不是调整真实数组的大小,例如请认为我们有这样的程序

        string[] names = new string[3] { "Parsa", "Nikan", "Neda" };
        AddArr(names, "Alex");
        foreach (var val in names)
        {
            Console.WriteLine(val);
        }
        Console.WriteLine(names.Length);

运行程序后可以看到输出是

Parsa
Nikan
Neda
3

Alex 的名字还没有添加到数组中

如果您在方法中设置断点,您可以在编译方法的第 13 行后看到 nums(方法中的参数)它已调整大小,但是当方法的编译结束时,您可以看到名称(数组) '未调整大小,但我可以通过在 Main 方法中编写代码自己解决此问题,但我想在单独的方法中编写此代码并且我不想使用列表

【问题讨论】:

  • 您需要声明string[] nums 参数作为参考:ref string[] nums。否则,数组引用的副本将传递给方法,Array.Resize() 将修改该副本而不是实际引用。
  • 你不能永远调整数组的大小; 根据定义,数组是固定大小的。最好使用List&lt;string&gt; nums 或类似名称,然后调用nums.Add(...);(是的,您可以使用Array.Resize 之类的名称,但这个名称是骗人的:应该叫Array.CreateNewArrayWithDifferentSizeAndCopyTheData
  • 我在文中说过我不想使用列表
  • @ParsaAghasi 这就像说“帮我用螺丝刀钉钉子;我在文中说过我不想用锤子”——我的意思是,当然,你可以,但这并不是做事的好方法
  • @ParsaAghasi 以更具建设性的方式重新表述:你不必回答这个问题,但我会非常好奇为什么你想以这种方式做事,因为目标听起来可能是基于一些误解。如果是这样,最好纠正误解并使用正确的工具来完成工作,而不是通过艰难的方式确切地学习如何做事。

标签: c# arrays function methods


【解决方案1】:
string[] names = new string[3] { "Parsa", "Nikan", "Neda" };
string[] names2 = new string[1] { "Alex" };

var newArray = new int[names.Length + names2.Length];

names.CopyTo(newArray , 0);
names2.CopyTo(newArray , x.Length);

或者你可以创建一个方法:

public static string[] AddArr(string[] names, string[] names2)
{
    var newArray = new int[names.Length + names2.Length];

    names.CopyTo(newArray , 0);
    names2.CopyTo(newArray , x.Length);

    return newArray;
}

【讨论】:

  • 我想在方法中使用它
【解决方案2】:

为了解决这个问题,我们应该像这样使用 ref

public static void AddArr(ref string[] nums, params string[] n)
        {
            string[] l = new string[nums.Length + n.Length];
            int j;
            for (j = 0; j < nums.Length; j++)
            {
                l[j] = nums[j];
            }
            for (int h = 0; h < n.Length; h++, j++)
            {
                l[j] = n[h];
            }
            Array.Resize(ref nums, l.Length);
            for (int f = 0; f < nums.Length; f++)
            {
                nums[f] = l[f];
            }
        }

这是问题的答案 感谢 Matthew Watson 提供此解决方案

【讨论】:

    【解决方案3】:

    你可以像这样修改你的代码:

    public static void AddArr(ref string[] nums, params string[] n)
    {
        string[] l = new string[nums.Length + n.Length];
        int j;
        for (j = 0; j < nums.Length; j++)
        {
            l[j] = nums[j];
        }
        for (int h = 0; h < n.Length; h++, j++)
        {
            l[j] = n[h];
        }
        Array.Resize(ref nums, l.Length);
        for (int f = 0; f < nums.Length; f++)
        {
            nums[f] = l[f];
        }
    

    }

    static void Main()
    {
       string[] names = new string[3] { "Parsa", "Nikan", "Neda" };
       AddArr(ref names, "Alex");
       foreach (var val in names)
       {
           Console.WriteLine(val);
       }
       Console.WriteLine(names.Length);
     }
    

    现在它会得到正确的结果:

    Parsa
    Nikan
    Neda
    Alex
    4
    

    您只需将“names”变量作为引用传递,以便在将其传递给 AddArr() 函数后更改仍然存在。

    【讨论】:

      【解决方案4】:

      缺少的一点是,要让您现有的代码工作,nums 需要通过引用传递,以便更改(在Array.Resize 中)向外传播到收集器:

      public static void AddArr(ref string[] nums, params string[] n)
      {
          // ...
      }
      // ...
      AddArr(ref names, "Alex");
      

      但是!这是一个糟糕的解决方案。 在所有方面,集合或列表类型更可取。

      【讨论】:

      • @Zer0 裸数组实在是太可怕了;如果您想走那条路-从贸易公司的角度来看,我认为您希望查看租用阵列的跨度,以减少分配;重新将它作为引用类型的“问题”:数组是引用类型......那么?再说一遍:如果你想全力以赴:跨越非托管内存。自定义引用类型集合可以做一些有趣的事情,比如在内部使用数组池,所以即使它们调整大小:分配是摊销而不是浪费。细节很重要,但裸数组从来都不是很好,部分原因是确切的长度问题。
      猜你喜欢
      • 2012-10-06
      • 2016-05-02
      • 1970-01-01
      • 2017-01-05
      • 2013-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-02
      相关资源
      最近更新 更多