C# 为什么集合分配在方法和连续行中的行为不同?
从下面的结果中,我想知道为什么“测试2”的值为30, 我希望得到与“测试3”(100)相同的结果 这里是更好理解的fiddler链接C# 为什么集合分配在方法和连续行中的行为不同?,c#,asp.net,C#,Asp.net,从下面的结果中,我想知道为什么“测试2”的值为30, 我希望得到与“测试3”(100)相同的结果 这里是更好理解的fiddler链接 IList<Test> initialCollection = new List<Test>(); initialCollection.Add(new Test(){ Value = 30}); Console.WriteLine("Test 1 : Before update method : " + initialCollection
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 );
在第二次测试之前,将
initialCollection
中的值的副本传递给UpdateValueCollection
,在该方法中,忽略传递的值,创建一个新列表,然后修改该列表。此方法永远不会对此方法的任何调用方产生任何可观察的影响
在测试3之前,您创建一个新列表,给它一个值,然后将其分配给initialCollection
,对该变量的值进行变异。由于您更改了该变量的值,与第二次测试不同,当您稍后获得该变量的值时,它会产生可观察的效果
如果方法UpdateValueCollection
通过引用(通过使用ref
或out
关键字)而不是通过值传递参数,那么对参数的更改也会影响initialCollection
,但由于它是通过值传递的,所以只有变量的副本发生了变异
请注意,如果您确实希望
UpdateValueCollection
为变量计算一个新列表,更惯用的设计是让UpdateValueCollection
返回一个新列表,而不是void
,然后,要在第二次测试之前将该方法的值分配给initialCollection
,您需要将initialCollection
中的值副本传递给UpdateValueCollection
,在该方法中,您忽略传递的值,创建一个新列表,然后修改该列表。此方法永远不会对此方法的任何调用方产生任何可观察的影响
在测试3之前,您创建一个新列表,给它一个值,然后将其分配给initialCollection
,对该变量的值进行变异。由于您更改了该变量的值,与第二次测试不同,当您稍后获得该变量的值时,它会产生可观察的效果
如果方法UpdateValueCollection
通过引用(通过使用ref
或out
关键字)而不是通过值传递参数,那么对参数的更改也会影响initialCollection
,但由于它是通过值传递的,所以只有变量的副本发生了变异
请注意,如果您确实希望
UpdateValueCollection
为变量计算一个新列表,更惯用的设计是让UpdateValueCollection
返回一个新列表,而不是void
,然后在调用lstest=check时,将该方法的值分配给initialCollection
在UpdateValueCollection
中,您仅更新该方法中可见的引用lstest
,您需要通过引用lstest
,才能替换列表本身,并使其在UpdateValueCollection
方法之外可见:
public void UpdateValueCollection(ref IList<Test> lstTest)
{
IList<Test> check = new List<Test>();
check.Add(new Test(){ Value = 100});
lstTest = check;
}
public void UpdateValueCollection(ref IList lstest)
{
IList check=新列表();
check.Add(newtest(){Value=100});
测试=检查;
}
当您调用lstest=check时
在UpdateValueCollection
中,您仅更新该方法中可见的引用lstest
,您需要通过引用lstest
,才能替换列表本身,并使其在UpdateValueCollection
方法之外可见:
public void UpdateValueCollection(ref IList<Test> lstTest)
{
IList<Test> check = new List<Test>();
check.Add(new Test(){ Value = 100});
lstTest = check;
}
public void UpdateValueCollection(ref IList lstest)
{
IList check=新列表();
check.Add(newtest(){Value=100});
测试=检查;
}
这些“奇怪”的事情可能会发生,因为您为方法提供了对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;
}
public void UpdateValueCollection(ref IList lstest)
{
IList check=新列表();
check.Add(newtest(){Value=100});
测试=检查;
}
这些“奇怪”的事情可能会发生,因为您为方法提供了对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;
}
public void UpdateValueCollection(ref IList lstest)
{
IList check=新列表();
check.Add(newtest(){Value=100});
测试=检查;
}
因为C#是按副本传递的(除非您在传递引用类型时使用ref
或out
),所以会生成该引用的副本。您可以对它引用的内容进行变异,但调用者将看不到指定的新值。因为C#是按副本传递的(除非您在传递引用类型时使用ref
或out
),所以会生成该引用的副本。您可以改变它所引用的内容,但调用者将看不到指定的新值。