Visual Studio 2017中C#类实例值修改异常问题求助
嘿,我一眼就揪出这个问题的根源啦!你遇到的这个“修改一个值其他值跟着变”的诡异情况,本质是C#数组的引用类型特性在搞鬼。
问题到底出在哪?
你补充里提到的细节就是关键:初始化TestResults时,activations、magnitudes、biases这三个字段,你传入的是同一个resultsFloats数组实例!
数组在C#里是引用类型,不是值类型——这意味着这三个字段并没有各自拥有独立的数组,它们只是指向内存里同一个数组对象的“指针”。就像你给三个人发了同一个房间的钥匙,不管谁进去改了房间里的东西,另外两个人开门看到的都是改过的版本。
所以你代码里给result.biases[l, i]赋值的时候,其实和修改result.activations[l, i]是在操作同一个数组的同一个位置,这就解释了为什么最后activations的值会和biases完全一致,完全偏离了你预期的nodes[l, i].value。
怎么解决?
核心思路就是给TestResults的每个数组字段分配独立的数组副本,而不是共用同一个实例。这里有两种简单靠谱的方式:
方式1:在构造函数里自动克隆数组
直接修改TestResults的构造函数,给每个传入的数组做克隆,确保每个字段都拿到独立的实例:
public class TestResults { public int finalResult; public float[,] activations; public float[,] magnitudes; public float[, ,] weights; public float[,] biases; public int actual; public TestResults(int newF, float[,] newAct, float[,] newMag, float[, ,] newW, float[,] newB, int newA) { finalResult = newF; // 克隆数组,生成独立的新实例 activations = (float[,])newAct.Clone(); magnitudes = (float[,])newMag.Clone(); weights = (float[, ,])newW.Clone(); biases = (float[,])newB.Clone(); actual = newA; } }
多维数组的Clone()方法会创建一个浅拷贝(这里数组里都是值类型的float,浅拷贝完全够用),完美满足我们的需求。
方式2:创建实例时手动传克隆后的数组
如果你不想修改TestResults的构造函数,也可以在创建实例的时候,手动给每个数组参数做克隆:
// 假设这里是你创建TestResults的代码 var testResult = new TestResults( yourFinalResultValue, (float[,])resultsFloats.Clone(), // 给activations传副本 (float[,])resultsFloats.Clone(), // 给magnitudes传副本 yourWeightsArray.Clone() as float[,,], // 权重数组同理 (float[,])resultsFloats.Clone(), // 给biases传副本 yourActualValue );
验证是否修复
你可以在修复后加一行代码验证:
bool areSame = object.ReferenceEquals(testResult.activations, testResult.biases);
如果返回false,就说明三个数组已经是独立的实例了,不会再出现同步修改的问题。
另外你提到“单独测试新创建的TestResults实例无此问题”,这是因为单独测试时你大概率给每个字段传了不同的数组实例,没有触发引用共享的坑~
内容的提问来源于stack exchange,提问作者R Gehrlein

