为什么集合赋值在方法和连续行中的行为不同?

时间:2015-04-01 17:15:41

标签: c# asp.net

  

从下面的结果中,我想知道为什么'测试2'的值为30,   我期望与“测试3”(100)中的结果相同?

以下是提琴手链接https://dotnetfiddle.net/Rco1mD以便更好地理解。

IList<Test> initialCollection = new List<Test>();
initialCollection.Add(new Test(){ Value = 30});

Console.WriteLine("Test 1 : Before update method : " + initialCollection.Last().Value );

UpdateValueCollection(initialCollection);

Console.WriteLine("Test 2: After update method : " + initialCollection.Last().Value );
IList<Test> check = new List<Test>();
check.Add(new Test(){ Value = 100});
initialCollection = check;

Console.WriteLine("Test 3: Same update method code added as consecutive line : " + initialCollection.Last().Value );

我的另一种方法是

public void UpdateValueCollection(IList<Test> lstTest)
{
   IList<Test> check = new List<Test>();
   check.Add(new Test(){ Value = 100});
   lstTest = check;
}

结果

Test 1 : Before update method : 30
Test 2 : After update method : 30
Test 3 : Same update method code added as consecutive line : 100

3 个答案:

答案 0 :(得分:3)

在第二次测试之前,您将initialCollection中的值的副本传递给UpdateValueCollection,在该方法中,您忽略传递的值,创建新列表,然后修改该列表。此方法永远不会对此方法的任何调用者产生任何可观察到的影响。

在测试3之前,您创建一个新列表,为其赋值,然后将其分配给initialCollection改变该变量的值。由于您更改了此变量的值,因此与第二次测试不同,当您稍后获取该变量的值时,它会产生可观察的效果。

如果方法UpdateValueCollection通过参考(通过使用refout关键字)而不是按值<传递参数 / em>,然后对参数的更改也会影响initialCollection,但是当它按值传递时,只变量的副本被突变。

请注意,如果您真的希望UpdateValueCollection为您的变量计算新列表,则更为惯用的设计是UpdateValueCollection 返回新列表而不是{ {1}},然后将该方法的值分配给void

答案 1 :(得分:1)

当您在lstTest = check;内致电UpdateValueCollection时,您只更新该方法中可见的参考lstTest,您需要通过引用传递lstTest才能更换列表本身并在UpdateValueCollection方法之外可见:

public void UpdateValueCollection(ref IList<Test> lstTest)
{
   IList<Test> check = new List<Test>();
   check.Add(new Test(){ Value = 100});
   lstTest = check;
}

答案 2 :(得分:0)

这些“奇怪”的事情可能会发生,因为你给你的方法一个IList的引用。如果现在更改IList的值,则仅在此方法中更新引用。 这意味着你现在可以在RAM的其他部分玩。

要解决此问题,您必须更改对IList引用的引用。 喜欢这个

public void UpdateValueCollection(ref IList<Test> lstTest)
{
   IList<Test> check = new List<Test>();
   check.Add(new Test(){ Value = 100});
   lstTest = check;
}