在数组上使用Func<>导致输入数组受影响的原因及解决方法
为什么array1和test会被修改?
这事儿的核心在于C#里数组是引用类型,不是值类型。当你做这些操作的时候:
float[] test = array1;:这里test并没有复制array1的内容,而是拿到了指向同一个数组对象的引用。- 把array1传给UseFunc的input参数:同样,input也是指向内存中那个原始数组的引用,不是新的副本。
所以在UseFunc里循环修改input[i] = func(...),本质上是直接修改了内存里的那个原始数组。既然array1、test、input都指向同一个数组,那它们自然都会看到修改后的结果——也就是4啦。
怎么解决这个问题?
有两种常见的思路,看你需求选:
方案1:让UseFunc返回新数组,不修改原数组
修改UseFunc方法,创建一个全新的数组来存储计算结果,而不是直接修改传入的数组:
public static float[] UseFunc(float[] input, float[] input2, Func<float, float, float> func) { // 新建一个和输入数组长度一致的结果数组 float[] resultArray = new float[input.Length]; for (int i = 0; i < input.Length; i++) { // 把计算结果存入新数组,原数组不动 resultArray[i] = func(input[i], input2[i]); } return resultArray; }
这样调用后,原array1和test的内容还是2,只有newArray是计算后的4,输出会变成4 2 2,完全符合预期。
方案2:调用方法时传入原数组的副本
如果你不想修改UseFunc的逻辑,可以在调用它的时候,先把array1复制一份,传给方法的是副本而不是原数组的引用:
方式A:用Clone()方法
float[] newArray = UseFunc((float[])array1.Clone(), array2, multiply);
Clone()会返回一个新的数组对象,里面的元素是原数组的副本。
方式B:用LINQ的ToArray()
如果引用了System.Linq的话,也可以这么写:
float[] newArray = UseFunc(array1.ToArray(), array2, multiply);
ToArray()同样会创建原数组的浅拷贝,适合这种值类型元素的数组。
这样方法里修改的是副本,原array1和test完全不受影响,结果也是正确的。
内容的提问来源于stack exchange,提问作者hulachop2
相关产品推荐
相关产品推荐

