【问题标题】:C# Add extension Append method to class array of type T [duplicate]C#将扩展Append方法添加到T类型的类数组[重复]
【发布时间】:2017-02-23 09:29:49
【问题描述】:

将这个answer 用于问题“How to add a string to a string[] array? There's no .Add function”我正在尝试使用this answer 编写一个通用扩展来将元素附加到generic array。仅使用Array.Resize() 方法效果很好,下面的示例为我的string array 添加了一个额外的元素

string[] array = new string[] { "Foo", "Bar" };
Array.Resize(ref array, array.Length + 1);
array[array.Length - 1] = "Baz";

但是当我尝试使用下面描述的 ArrayExtension 方法时,该方法确实在方法内调整了我的数组的大小,但是当它返回时数组没有改变?

我的扩展类

public static class ArrayExtensions
{
    public static void Append<T>(this T[] array, T append)
    {
        Array.Resize(ref array, array.Length + 1);
        array[array.Length - 1] = append;    // < Adds an extra element to my array
    }
}

如下使用

string[] array = new string[] { "Foo", "Bar" };
array.Append("Baz");

当方法返回时,添加的元素不存在。我错过了什么?

更新

正如所指出的,这个问题之前已经在这里提出并回答过。我将接受上一个问题“Changing size of array in extension method does not work?”作为我问题的答案。

更新 2

由于如果在扩展方法中使用了返回方法,它确实违反了框架中 Append() 修改对象本身的类似类的预期行为,因此我对扩展方法进行了一些更改以防止它被错误地用过的。感谢@NineBerry 指出这一点。

我还添加了params T[] add 以允许一次添加多个元素。

public static class ArrayExtensions
{
    /// <summary>
    /// Creates a copy of an object array and adds the extra elements to the created copy
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="array"></param>
    /// <param name="add">Elemet to add to the created copy</param>
    /// <returns></returns>
    public static T[] CopyAddElements<T>(this T[] array, params T[] add)
    {
        for (int i = 0; i < add.Length; i++)
        {
            Array.Resize(ref array, array.Length + 1);
            array[array.Length - 1] = add[i];
        }
        return array;
    }
}

用法

string[] array = new string[] { "Foo", "Bar" };
array = array.CopyAddElements("Baz", "Foobar");
for (int i = 0; i < array.Length; i++)
{
    System.Console.Write($"{array[i]} ");
}

/* Output
 *  Foo Bar Baz Foobar
*/

【问题讨论】:

  • Array.Resize 是一种欺骗。它实际上是一个新对象的副本。从那里可以得出,您需要一个 ref 参数才能对实际参数产生影响。

标签: c# arrays generics append extension-methods


【解决方案1】:

Array.Resize 创建一个新数组。这就是为什么您必须使用ref 关键字将数组传递给Array.Resize。所以,从Array.Resize 返回后,变量array 引用了不同的对象。

没有办法使用扩展方法来做你想做的事情。

为什么不简单地使用 List 而不是数组呢?使用Array.Resize 是一项非常昂贵的操作。这意味着每次调用它以增加数组长度时,分配新内存并将数据从旧数组复制到新数组。

【讨论】:

  • 请在回答的第一句话中提出建议List。这才是真正的解决方案。
【解决方案2】:

实际发生的是

array.Append("Baz");

被翻译成

ArrayExtensions.Append( array, "Baz" );

这意味着对array 的引用是通过 传入的,因此在Append 方法中,您使用的是引用的副本。然后Array.Resize 方法将这个新变量作为ref,在内存中创建一个新数组,并将变量更改为指向它。不幸的是,这只改变了这个变量,而不是原来的变量

您可以将新创建​​的数组作为返回值返回,或者创建一个使用ref 的静态方法而不是扩展方法。

【讨论】:

    【解决方案3】:

    与您的直觉相反,this 参数未通过隐式 ref 传递,也不允许向其添加 ref。另见讨论here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-30
      • 2013-04-19
      相关资源
      最近更新 更多