Why is list when passed without ref to a function acting like passed with ref?
If I did not get this terribly wrong, this behaviour is strange for me. Rather than explaining, I'll post a sample code below and please tell me why does I get output x and not 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);
}
Output should, I assume would be 3. But I get the output as 5. I understand the output can be 5 if I do this:
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);
}
It does not act like its passed by ref.
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);
}
Try it. Do you notice the difference?
You can only change the contents of list (or any reference type) if you pass it without a ref (because as others have said, you are passing a reference to the object on the heap and thus change the same "memory").
However you cannot change "list", "list" is a variable that points to an object of type List. You can only change "list" if you pass it by reference (to make it point somewhere else). You get a copy of the reference, which if changed, can only be observed inside your method.
Parameters are passed by value in C# unless they are marked with the ref
or out
modifiers. For reference types, this means that the reference is passed by value. Therefore, in Fuss
, l
is referring to the same instance of List<int>
as its caller. Therefore, any modifications to this instance of List<int>
will be seen by the caller.
Now, if you mark the parameter l
with ref
or out
, then the parameter is passed by reference. What this means is that in Fuss
, l
is an alias for storage location used as a parameter to invoke the method. To be clear:
public void Fuss(ref List<int> l)
called by
List<int> list = new List<int> { 1, 2, 3 };
Fuss(list);
Now, in Fuss
, l
is an alias for list
. In particular, if you assign a new instance of List<int>
to l
, the caller will see that new instance assigned to the variable list
as well. In particular, if you say
public void Fuss(ref List<int> l) {
l = new List<int> { 1 };
}
then the caller will now see a list with one element. But if you say
public void Fuss(List<int> l) {
l = new List<int> { 1 };
}
and call by
List<int> list = new List<int> { 1, 2, 3 };
Fuss(list);
then the caller will still see list
as having three elements.
Clear?
The difference between ref and non-ref for reference types like List is not whether you pass a reference (that happens always), but whether that reference can be changed. Try the following
private void Fuss(ref List<int> l)
{
l = new List<int> { 4, 5 };
}
and you'll see the count is 2, because the function not only manipulated the original list but the reference itself.
链接地址: http://www.djcxy.com/p/3562.html上一篇: C#.Net案例