I was following along a tutorial online about C#. The tutorial talks about passing-by-reference vs passing-by-value. What I am confused about specifically is that since in C#, there is a distinction between reference types vs value types, how does that distinction affect the output of the following two functions.
In the following code snippet:
public void CanSetNameFromReference()
{
Book book1 = GetBook("Book 1");
SetName(book1, "New Name");
Assert.Equal("New Name", book1.Name);
}
private void SetName(Book book, string name)
{
book.Name = name;
}
We pass in an object of type Book into SetName and we see that SetName correctly sets the name of book1 to "New Name", even though book is being passed by reference.
On the other hand in the code snippet below, this does not seem to be the case:
public void CSharpIsPassByValue()
{
var book1 = GetBook("Book 1");
GetBookSetName(book1, "New Name");
Assert.Equal("Book 1", book1.Name);
}
private void GetBookSetName(Book book, string name)
{
book = new Book(name);
}
Why is this the case?
Finally, in the code snippet below,
public void CSharpCanPassByReference()
{
var book1 = GetBook("Book 1");
GetBookSetName(ref book1, "New Name");
Assert.Equal("New Name", book1.Name);
}
private void GetBookSetName(ref Book book, string name)
{
book = new Book(name);
}
we are passing in by reference. In this case, what is happening? How is this different from the first case?
You've confused "pass by reference" with "reference type." Reference types are passed by value by default, unless you use the ref
keyword. When you pass a reference type by value, it is the same as passing anything by value; you are passing a copy. In this case, you are passing a copy of the reference.
In this example...
private void SetName(Book book, string name)
{
book.Name = name;
}
...you are passing a reference type by value. The variable book
is populated with a copy of the caller's variable book1
. However, the variable itself contains a reference to the same Book
object as the caller's, so setting its properties shows up in both places.
In this example...
private void GetBookSetName(Book book, string name)
{
book = new Book(name);
}
...you are also passing a reference type by value. However, you are overwriting the (copied) value with a reference to a new Book
. It's just a copy, and has no effect on book1
.
In this example...
private void GetBookSetName(ref Book book, string name)
{
book = new Book(name);
}
...you are passing a reference type by reference. The method receives a pointer to the original reference, which it can change. Therefore when you assign it a new Book
, it shows up in both places.