在扩展方法中更改数组的大小不起作用?
所以基本上我为数组类型编写了一个小的Add
扩展方法。
using System; using System.Linq; public static class Extensions { public static void Add(this T[] _self, T item) { _self = _self.Concat(new T[] { item }).ToArray(); } } public class Program { public static void Main() { string[] test = { "Hello" }; test = test.Concat(new string[] { "cruel" }).ToArray(); test.Add("but funny"); Console.WriteLine(String.Join(" ", test) + " world"); } }
输出应该是Hello cruel but funny world
, but funny
永远不会在扩展方法中连接。
在扩展中编辑相同的数组似乎也不起作用:
using System; using System.Linq; public static class Extensions { public static void Add(this T[] _self, T item) { Array.Resize(ref _self, _self.Length + 1); _self[_self.Length - 1] = item; } } public class Program { public static void Main() { string[] test = { "Hello" }; test = test.Concat(new string[] { "cruel" }).ToArray(); test.Add("but funny"); Console.WriteLine(String.Join(" ", test) + " world"); } }
我在这里遇到了什么问题,如何将其用作扩展?
.dotNet小提琴: https ://dotnetfiddle.net/9os8nY或https://dotnetfiddle.net/oLfwRD
(找到一种方法很好,所以我可以保持呼叫test.Add("item");
)
您正在为参数分配新引用,除非将其作为ref
参数传递,否则它不会更改实际数组。 由于这是一种扩展方法,因此不是一种选择。 所以考虑使用常规方法:
public static void Add(ref T[] _self, T item) { _self = _self.Concat(new T[] { item }).ToArray(); } Add(ref test, "but funny");
或者如果你坚持使用扩展方法,你需要使用数组第二个参数才能使用ref:
public static void AddTo(this T item, ref T[] arr, ) { arr = arr.Concat(new T[] { item }).ToArray(); } "but funny".AddTo(ref test);
Array.Resize
不起作用。 因为它改变了_self
,而不是test
数组。 现在,当您传递不带ref
关键字的引用类型时,将复制引用。 它是这样的:
string[] arr1 = { "Hello" }; string[] arr2 = arr1;
现在,如果你为arr2
分配一个新的引用,它将不会改变arr1
的引用Array.Resize
正在做的是,由于无法调整数组大小,它会创建一个新数组并将所有元素复制到一个新数组,它为参数赋予了新的引用(在这种情况下为_self
)。因此它改变了_self
指向的位置,但由于_self
和test
是两个不同的引用(如arr1
和arr2
),更改其中一个不会影响另一个。
另一方面,如果你将array作为ref
传递给你的方法,就像在我的第一个例子中那样, Array.Resize
也将按预期工作,因为在这种情况下,引用将不会被复制:
public static void Add(ref T[] _self, T item) { Array.Resize(ref _self, _self.Length + 1); _self[_self.Length - 1] = item; }
我相信_self =
将_self
对象的副本创建为为参数_self
创建的局部变量 – 因此原始文件不会更新。 使用类似列表的引用类型,或创建一个返回新数组的静态方法。
根据原因的“感觉”:你在变量实例上调用一个方法 – 你不能在它的上下文中执行的代码中更改该实例
您可以更改这样的代码:
public static class Extensions { public static T[] Add(this T[] _self, T item) { return _self.Concat(new T[] { item }).ToArray(); } } public class Program { public static void Main() { string[] test = { "Hello" }; test = test.Concat(new string[] { "cruel" }).ToArray(); test = test.Add("but funny"); Console.WriteLine(String.Join(" ", test) + " world"); } }
作为旁注 – 用法与Concat方法相同。