我对这段代码很困惑。即使我也阅读了@John Skeet的博客http://jonskeet.uk/csharp/references.html,我仍然对最后一篇文章感到有些困惑。图表表示将非常有用。
static void Main(string[] args)
{
List<int> myList = new List<int>();
myList.Add(100);
myList.Add(50);
myList.Add(10);
ChangeList(myList);
foreach (var item in myList)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
private static void ChangeList(List<int> myList)
{
myList.Sort();
List<int> myList2 = new List<int>();
myList2.Add(3);
myList2.Add(4);
myList = myList2;
}
为什么输出是10,50和100.最后一行发生了什么myList = myList2;为什么无论我评论该行,还是取消注释输出仍然保持不变。
答案 0 :(得分:4)
最后一行实际上没有效果,因为myList
只是一个包含对实际列表的引用的变量。该变量本身是 - 作为 C#中的每个参数 - 通过值传递给方法,对其进行任何更改 该方法无效< em>在来电者上。这与为方法提供int完全相同:
void DoSomething(int a)
{
a = 3
}
调用DoSomething(myInt)
之类的方法不会更改myInt
的值,因为数字是按值传递的。在您的示例中,引用只是一个数字(或更准确地说是内存地址)。在您的方法中更改该地址对外部没有影响。
通过撰写myList = myList2
,您可以指定一个与初始无关的新参考。
要实现这一目标,您需要ref-keyword:
private static void ChangeList(ref List<int> myList)
{
myList.Sort();
List<int> myList2 = new List<int>();
myList2.Add(3);
myList2.Add(4);
myList = myList2;
}
现在这样称呼:
ChangeList(ref myList);
答案 1 :(得分:0)
所以List<T>
是引用类型。这意味着myList
拥有一个指向此List<int>
对象的存储位置的引用。现在您调用ChangeList(List<int> myList)
,然后您可能会认为myList
已更改。
但实际上,您已将myList
的本地副本作为方法参数传递给ChangeList
。因此,您更改了myList
的本地副本的项目,该副本仅存在于ChangeList()
方法中。
通过将ref
添加到方法参数中,您不会传递myList
的副本,而是将引用传递给对象,因此两个List<int>
对象现在都指向同一个对象在存储上。因此,myList
中Main()
项的值会发生变化,因为它们都引用相同的List<int>
。
private static void ChangeList(ref List<int> myList)
{
myList.Sort();
List<int> myList2 = new List<int>();
myList2.Add(3);
myList2.Add(4);
myList = myList2;
}
现在您必须使用ref
关键字调用该方法。
ChangeList(ref myList);