为什么列表在没有引用的情况下传递给像ref一样传递的函数?
如果我没有得到这个可怕的错误,这种行为对我来说很奇怪。 而不是解释,我会在下面发布一个示例代码,请告诉我为什么我会得到输出x而不是y。
private void button1_Click(object sender, EventArgs e)
{
List<int> l = new List<int>() { 1, 2, 3 };
Fuss(l);
MessageBox.Show(l.Count.ToString());
}
private void Fuss(List<int> l)
{
l.Add(4);
l.Add(5);
}
输出应该,我假设将是3.但我得到的输出为5.我知道输出可以是5,如果我这样做:
private void button1_Click(object sender, EventArgs e)
{
List<int> l = new List<int>() { 1, 2, 3 };
Fuss(ref l);
MessageBox.Show(l.Count.ToString());
}
private void Fuss(ref List<int> l)
{
l.Add(4);
l.Add(5);
}
它不像它通过参考。
void ChangeMe(List<int> list) {
list = new List<int>();
list.Add(10);
}
void ChangeMeReally(ref List<int> list) {
list = new List<int>();
list.Add(10);
}
尝试一下。 你注意到了区别吗?
如果你在没有引用的情况下传递它,你只能改变列表的内容(或者任何引用类型)(因为正如其他人所说的那样,你正在传递一个引用到堆上的对象并因此改变相同的“内存”)。
但是,您不能更改“列表”,“列表”是指向List类型的对象的变量。 只有通过引用传递它才能更改“列表”(使其指向其他位置)。 你会得到一份参考文献,如果改变了,只能在你的方法中观察到。
参数是通过C#中的值传递的,除非它们用ref
或out
修饰符标记。 对于引用类型,这意味着引用是按值传递的。 因此,在Fuss
, l
指的是List<int>
的同一个实例作为其调用者。 因此,对这个List<int>
实例的任何修改都会被调用者看到。
现在,如果用ref
或out
标记参数l
,那么该参数将通过引用传递。 这意味着在Fuss
, l
是存储位置的别名,用作调用该方法的参数。 要清楚:
public void Fuss(ref List<int> l)
由...调用
List<int> list = new List<int> { 1, 2, 3 };
Fuss(list);
现在,在Fuss
, l
是list
的别名。 特别是,如果将一个新的List<int>
实例分配给l
,则调用者也会看到分配给变量list
新实例。 特别是,如果你说
public void Fuss(ref List<int> l) {
l = new List<int> { 1 };
}
那么调用者现在将看到一个包含一个元素的列表。 但如果你说
public void Fuss(List<int> l) {
l = new List<int> { 1 };
}
并通过
List<int> list = new List<int> { 1, 2, 3 };
Fuss(list);
那么调用者仍然会看到list
有三个元素。
明确?
像List这样的引用类型的ref和non-ref之间的差异不是你是否传递引用(总是会发生),而是引用是否可以改变。 尝试以下操作
private void Fuss(ref List<int> l)
{
l = new List<int> { 4, 5 };
}
你会看到count是2,因为这个函数不仅操纵了原始列表,而且还引用了它本身。
链接地址: http://www.djcxy.com/p/3561.html上一篇: Why is list when passed without ref to a function acting like passed with ref?