提问人:user1234 提问时间:8/1/2022 最后编辑:user1234 更新时间:8/1/2022 访问量:56
C# 中按值传递与按引用传递的含义 [重复]
Implications of pass-by-value vs pass-by-reference in C# [duplicate]
问:
我正在关注有关 C# 的在线教程。本教程讨论按引用传递与按值传递。我特别感到困惑的是,由于在 C# 中,引用类型与值类型之间存在区别,那么这种区别如何影响以下两个函数的输出。
在以下代码片段中:
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;
}
我们将 Book 类型的对象传递到 SetName 中,我们看到 SetName 正确地将 book1 的名称设置为“New Name”,即使 book 是通过引用传递的。
另一方面,在下面的代码片段中,情况似乎并非如此:
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);
}
为什么会这样?
最后,在下面的代码片段中,
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);
}
我们通过引用传递。在这种情况下,发生了什么?这与第一种情况有何不同?
答:
您混淆了“通过引用传递”和“引用类型”。默认情况下,引用类型按值传递,除非使用关键字。按值传递引用类型时,它与按值传递任何内容相同;您正在传递副本。在本例中,您将传递引用的副本。ref
在此示例中...
private void SetName(Book book, string name)
{
book.Name = name;
}
...您正在按值传递引用类型。该变量填充了调用方变量的副本。但是,变量本身包含对调用方对象的同一对象的引用,因此设置其属性会显示在两个位置。book
book1
Book
在此示例中...
private void GetBookSetName(Book book, string name)
{
book = new Book(name);
}
...您还按值传递引用类型。但是,您正在用对新 .它只是一个副本,对 .Book
book1
在此示例中...
private void GetBookSetName(ref Book book, string name)
{
book = new Book(name);
}
...您正在逐个引用传递引用类型。该方法接收指向原始引用的指针,它可以更改该指针。因此,当您为其分配 新 时,它会显示在两个位置。Book
评论
在第一种情况下,book 并不是真正通过引用传递的,而是一种引用类型。我们知道这一点,因为这是一个引用类型。回复:https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/reference-types,而不是值类型。Book
因此,当第一个示例私有设置时,它会在它传递的引用类型的引用中执行该操作。book.Name = name;
book
在第二个示例中,您设置为一个 NEW 类型,该类型为引用创建一个 NEW book,然后设置该 of (这不是一个好的做法,因为它实际上在做两件事)——当然,原始引用不知道 NEW book,只知道它引用的书。book
book
Book
Name
现在,在第三个示例中,您传递一个引用类型,然后将其更改为具有新名称的新引用 - 由于它是引用,因此原始引用将选取新对象和名称。ref
Book
book1
private void GetBookSetName(ref Book book, string name)
{
book = new Book(name);
}
如果它有帮助,对于最后一个例子来说,真的应该是这样。GetBookSetName
SetBookToNewBookWithNewName
评论