Does C# pass a List<T> to a method by reference or as a copy?
Solution 1
It's passed by reference. List<T>
is a class, and all class instances are passed by reference.
Solution 2
The behaviour is always the same: Passing by copying. In case the parameter is an object, the reference to the object is copied, so in fact you are working on the same object/list/whatever.
Solution 3
In addition to other answers it is very important to understand the behavior of ref
Here is some sample code for demonstration purpose
static void Main(string[] args)
{
List<string> lstStr = new List<string>();
lstStr.Add("First");
lstStr.Add("Second");
Alter(lstStr);
//Alter(ref lstStr);
Console.WriteLine("---From Main---");
foreach (string s in lstStr)
{
Console.WriteLine(s);
}
Alter2(ref lstStr);
Console.WriteLine("---From Main after passed by ref---");
foreach (string s in lstStr)
{
Console.WriteLine(s);
}
Console.ReadKey();
}
static void Alter(List<string> lstStr2)
{
lstStr2.Add("Third");
Console.WriteLine("----From Alter----");
foreach (string s in lstStr2)
{
Console.WriteLine(s);
}
lstStr2 = new List<string>();
lstStr2.Add("Something new");
Console.WriteLine("----From Alter - after the local var is assigned somthing else----");
foreach (string s in lstStr2)
{
Console.WriteLine(s);
}
}
static void Alter2(ref List<string> lstStr2)
{
lstStr2 = new List<string>();
lstStr2.Add("Something new from alter 2");
Console.WriteLine("----From Alter2 - after the local var is assigned new list----");
foreach (string s in lstStr2)
{
Console.WriteLine(s);
}
}
//----From Alter----
//First
//Second
//Third
//----From Alter - after the local var is assigned somthing else----
// Something new
// ---From Main---
// First
// Second
// Third
// ----From Alter2 - after the local var is assigned new list----
// Something new from alter 2
// ---From Main after passed by ref---
// Something new from alter 2
Solution 4
The underlying thing always is: value types are passed by value, and reference types are "passed by reference" (quoted because the value of the reference is actually passed by value, but most people ignore that for the sake of brevity).
The easiest way to reconcile the ref
keyword against references is: reference types have their reference passed by value. This has the effect, in the standard case, of simply passing the reference to the list (and not the entire list) to the method.
The ref
keyword, when used on a reference type, semantically passes a reference to the reference (I really struggle not to say "pointer to a pointer").
If your method were to re-assign the ref
argument to a new object, the caller would also see this new assignment. Whereas without the ref
keyword, the method would simply be re-assign their own local copy of the reference value and the caller would still have a reference to their original object.
The above explanation is shamelessly taken from Jon Skeet's article on the topic:
This difference is absolutely crucial to understanding parameter passing in C#, and is why I believe it is highly confusing to say that objects are passed by reference by default instead of the correct statement that object references are passed by value by default.
The ref
keyword is only needed if you intend to re-assign the argument and have that visible to the caller. In most cases you will find that it isn't needed. Your DoStuff
can be re-written to remove it and still pass a reference to the list by value successfully:
void DoSomething(List<string> strs)
{
strs.Add("Hello");
}
Solution 5
The ref
keyword in your method is redundant if you want to modify the original list: List<T>
is a reference type (class
in C#) and so will be passed to the method by reference; therefore the method will manipulate the original list.
When passing a Value Type
, it will create a copy of the value itself.
When passing a Reference Type
, it will create a copy of the reference.
Read more about Value and Reference Types in C#.
Related videos on Youtube
Scre
I code (mainly in C++, C#, and Kotlin, but do tinker with Ruby, Lua, and various other lingos). I play computer games, of course... lots of them. That's about all there is to say at the moment.
Updated on April 30, 2020Comments
-
Scre about 4 years
Taking my first steps in C# world from C/C++, so a bit hazy in details. Classes, as far as I understood, are passed by reference by default, but what about eg. List<string> like in:
void DoStuff(List<string> strs) { //do stuff with the list of strings }
and elsewhere
List<string> sl = new List<string>(); //next fill list in a loop etc. and then do stuff with it: DoStuff(sl);
Is sl in this case passed by reference or is a copy made so that I'd need to redefine the worker function like
void DoStuff(ref List<string> strs)
to actually act on sl itself and not a copy?-
Dialecticus almost 10 years
class
is passed by reference.struct
is passed by value. -
Kurubaran almost 10 yearsthis article should help you understand this area better.
-
Scre almost 10 yearsSeems "pass by reference" in C# and C++ are from different dictionaries. Anyhow, thank you all for the answers - hazy details now less hazy.
-
Admin almost 10 years@Scre Some people confusingly use "pass by reference" in a different sense in C#, because of the terms "reference" and "reference type" (which indeed refer to a different meaning of "reference"). But the correct use of "pass by reference" in C#,
ref
parameters, is almost identical to the thing called pass by reference in C++ and CS in general.
-
-
Admin almost 10 yearsThe
ref
is not redundant. With it,strs = ...;
affects the caller. Without it, it doesn't. -
Admin almost 10 yearsThe
ref
is not redundant. With it,strs = ...;
affects the caller. Without it, it doesn't. -
Tarec almost 10 yearsAlso, sending a reference type object to a method without
ref
keyword results in creating a new copy of the reference. "Redundant" would mean it's the same. And it is not. -
Scre almost 10 yearsThis was my first "hunch" about how it would work, but wasn't quite sure.
-
Adam Houldsworth almost 10 years@scre I highly recommend reading that Jon Skeet article and also picking up the C# in Depth book by him, he has a good skill for structuring an explanation of abstract or complex topics for easy consumption.
-
fabian almost 10 years(Not necesary for reference values)