c# - 为什么结构中的引用类型表现得像值类型?

标签 c# string value-type reference-type

我是 C# 编程的初学者。我现在正在研究 stringsstructsvalue typesreference types。作为 here 中接受的答案在here , strings 是引用类型,它们的指针存储在堆栈中,而它们的实际内容存储在堆中。此外,如 here 中所述, structs 是值类型。现在我试着用一个小例子来练习 structsstrings:

struct Person
{
    public string name;
}

class Program
{
    static void Main(string[] args)
    {
        Person person_1 = new Person();
        person_1.name = "Person 1";

        Person person_2 = person_1;
        person_2.name = "Person 2";

        Console.WriteLine(person_1.name);
        Console.WriteLine(person_2.name);
    }
}

上面的代码片段输出

Person 1
Person 2

这让我很困惑。如果 strings 是引用类型而 structs 是值类型,那么 person_1.name 和 person_2.name 应该指向堆上的相同空间区域,不是吗?

最佳答案

strings are reference types that have pointers stored on stack while their actual contents stored on heap

不不不。首先,停止考虑堆栈和堆。在 C# 中,这几乎总是错误的思考方式。 C# 为您管理存储生命周期。

其次,虽然引用可以实现为指针,但引用在逻辑上不是指针。引用是引用。 C# 有引用和指针。不要混淆它们。 C# 中从来没有指向字符串的指针。有对字符串的引用。

第三,对字符串的引用可以存储在堆栈中,但也可以存储在堆中。当您有一个字符串引用数组时,数组内容在堆上。

现在让我们来谈谈您的实际问题。

    Person person_1 = new Person();
    person_1.name = "Person 1";
    Person person_2 = person_1; // This is the interesting line
    person_2.name = "Person 2";

让我们从逻辑上说明代码的作用。你的 Person 结构只不过是一个字符串引用,所以你的程序是一样的:

string person_1_name = null; // That's what new does on a struct
person_1_name = "Person 1";
string person_2_name = person_1_name; // Now they refer to the same string
person_2_name = "Person 2"; // And now they refer to different strings

当您说 person2 = person1 时,并不意味着变量 person1 现在是变量 person2 的别名。 (在 C# 中有一种方法可以做到这一点,但事实并非如此。)它的意思是“将 person1 的内容复制到 person2”。对字符串的引用是复制的值。

如果不清楚,请尝试为变量绘制方框,为引用绘制箭头;复制结构时,会生成箭头的副本,而不是的副本。

关于c# - 为什么结构中的引用类型表现得像值类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40564712/

相关文章:

c# - 如何在 C# 中打开 Windows 7 事务处理文件

java - 如何拆分字符串并包含拆分器?

c# - 正确使用 MemoryCache 和泛型?

c# - 用于 C# 的 Quantlib 64 位?

c# - 添加在 Visual Studio 2017 RC 中构建 .NET Core 项目后运行的 msbuild 任务

xml - 提取 Xpath 中包含字符串的图像

c++ - 与模板方法不一致的字符串排序

c# - 泛型指针?

C#支持值类型和引用类型,但它们都是对象吗?

c# - 如何在 ASP.NET Web API 中执行异步 'fire and forget' 操作