C# 将扩展 Append 方法添加到 class 类型 T 数组
C# Add extension Append method to class array of type T
使用这个answer to the question "How to add a string to a string[] array? There's no .Add function" I am trying to use this answer to write an generic extension to append elements to an generic array
. Only using the Array.Resize()
method works well and the sample below adds an extra element to my string array
string[] array = new string[] { "Foo", "Bar" };
Array.Resize(ref array, array.Length + 1);
array[array.Length - 1] = "Baz";
但是当我尝试使用下面描述的 ArrayExtension 方法时,方法 会 在方法内调整我的数组大小,但是当它 return 时数组没有改变?
我的分机class
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");
方法returns时,添加的元素不存在。我错过了什么?
更新
如前所述,此问题已在此处提出和回答过。我将接受上一个问题“”作为我问题的答案。
更新 2
因为如果在扩展方法中使用 return 方法,它确实违反了框架中类似 classes 的预期行为,即 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
关键字将数组传递给 Array.Resize
。因此,从 Array.Resize
返回后,变量 array
引用了不同的对象。
无法使用扩展方法来完成您想要做的事情。
为什么不简单地使用 List<> 而不是数组?使用 Array.Resize
是一项非常昂贵的操作。这意味着每次调用它以增加数组长度时,分配新内存并将数据从旧数组复制到新数组。
与您的直觉相反,this
参数未通过隐式 ref
传递,也不允许向其添加 ref
。另见讨论 here
实际发生的是
array.Append("Baz");
翻译成
ArrayExtensions.Append( array, "Baz" );
这意味着对 array
的引用由 value 传入,因此在 Append
方法中您使用 copy参考。 Array.Resize
方法然后将这个新变量作为 ref
,在内存中创建一个 新数组 并将变量更改为指向它。不幸的是,只改变了这个变量,而不是原来的。
您可以 return 新创建的数组作为 return 值,或者创建一个使用 ref
而不是扩展方法的静态方法。
使用这个answer to the question "How to add a string to a string[] array? There's no .Add function" I am trying to use this answer to write an generic extension to append elements to an generic array
. Only using the Array.Resize()
method works well and the sample below adds an extra element to my string array
string[] array = new string[] { "Foo", "Bar" };
Array.Resize(ref array, array.Length + 1);
array[array.Length - 1] = "Baz";
但是当我尝试使用下面描述的 ArrayExtension 方法时,方法 会 在方法内调整我的数组大小,但是当它 return 时数组没有改变?
我的分机class
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");
方法returns时,添加的元素不存在。我错过了什么?
更新
如前所述,此问题已在此处提出和回答过。我将接受上一个问题“
更新 2
因为如果在扩展方法中使用 return 方法,它确实违反了框架中类似 classes 的预期行为,即 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
关键字将数组传递给 Array.Resize
。因此,从 Array.Resize
返回后,变量 array
引用了不同的对象。
无法使用扩展方法来完成您想要做的事情。
为什么不简单地使用 List<> 而不是数组?使用 Array.Resize
是一项非常昂贵的操作。这意味着每次调用它以增加数组长度时,分配新内存并将数据从旧数组复制到新数组。
与您的直觉相反,this
参数未通过隐式 ref
传递,也不允许向其添加 ref
。另见讨论 here
实际发生的是
array.Append("Baz");
翻译成
ArrayExtensions.Append( array, "Baz" );
这意味着对 array
的引用由 value 传入,因此在 Append
方法中您使用 copy参考。 Array.Resize
方法然后将这个新变量作为 ref
,在内存中创建一个 新数组 并将变量更改为指向它。不幸的是,只改变了这个变量,而不是原来的。
您可以 return 新创建的数组作为 return 值,或者创建一个使用 ref
而不是扩展方法的静态方法。