C# 为什么集合分配在方法和连续行中的行为不同?

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

从下面的结果中,我想知道为什么“测试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.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
),所以会生成该引用的副本。您可以改变它所引用的内容,但调用者将看不到指定的新值。