为什么字符串类型表现得像值类型?

Why does type of string behave like value type?

我对引用的类型感到非常困惑。搜索了一下,发现string类型是引用类型。不是吗?

我的问题是:

我将一个字符串变量复制到另一个,并更改了第一个的值,但第二个的值仍然相同。我不明白这个问题。即使字符串类型是引用类型,第二个也不会改变。我也尝试了装箱方法,但我无法获得结果。

我看了这篇文章In C#, why is String a reference type that behaves like a value type?,但还是一头雾水

这是我的代码:

        string my_text1 = "My text 1";
        string my_text2 = my_text1;

        my_text1 = "My text 2";
        Console.WriteLine("First text --> " + my_text1); // It prints My text 2
        Console.WriteLine("Second text -->" + my_text2); // It prints My text 1(I want it prints "My text 2" too)

        string text_1 = "Example 1";
        object text_2 = text_1;

        text_1 = "Example 2";
        Console.WriteLine("First example --> " + text_1); // It prints Example 2
        Console.WriteLine("Second example -->" + text_2);// It prints Example 1

就像 Damien_The_Unbeliever 指出的那样,赋值总是会更改该变量并且不会影响之前的变量。

考虑以下带有 类

的示例
class Program
{
    static void Main(string[] args)
    {
        Foo my_text1 = new Foo("My text 1");
        Foo my_text2 = my_text1;

        my_text1 = new Foo("My text 2");
        Console.WriteLine("First text --> " + my_text1); // It prints My text 2
        Console.WriteLine("Second text -->" + my_text2); // It prints My text 1

        Foo text_1 = new Foo("Example 1");
        object text_2 = text_1;

        text_1 = new Foo("Example 2");
        Console.WriteLine("First example --> " + text_1); // It prints Example 2
        Console.WriteLine("Second example -->" + text_2);// It prints Example 1
    }
}

class Foo
{
    private readonly string _name;

    public Foo(string name)
    {
        _name = name;
    }

    public override string ToString()
    {
        return _name;
    }
}

这样的字符串不太行,但它能让你明白Damien_The_Unbeliever是什么意思

如果你想让一个变量像引用一样,你应该添加 ref 关键字

string my_text1 = "My text 1";
ref string my_text2 = ref my_text1;

my_text1 = "My text 2";
Console.WriteLine("First text --> " + my_text1); // It prints My text 2
Console.WriteLine("Second text -->" + my_text2); // It prints My text 2

因为字符串是不可变的引用类型。

不可变类型是一种对象类型,其数据在创建后无法更改。不可变字符串有很多好处。它提高了运行时效率和安全性(进程不能通过注入某些东西来更改字符串)。你可以read它详细解释。

而且,字符串是引用类型的原因是,它们可能很大,需要存储在堆中。详情here

您可以使用可变的 StringBuilder。

StringBuilder my_text1 = new StringBuilder("My text 1");
StringBuilder my_text2 = new StringBuilder("My text 2");

my_text1 = my_text2;
Console.WriteLine("First text --> " + my_text1); 
Console.WriteLine("Second text -->" + my_text2);

在上面的例子中,两个表达式都会得到 "My text 2"。

赋值是影响变量的动作。变量本身是独立的。值类型和引用类型之间的重要区别在于 data 是存储在变量本身还是其他地方(并且变量仅包含引用)。

因此,当分配给一个变量时,您更改了该变量的内容1。这本身不会对任何其他变量产生明显影响。

当您改变数据 时,您经常会注意到值类型和引用类型之间的区别。在这里,差异很明显,因为当你改变一个值类型的数据时,你是通过一个特定的变量来完成的,而你正在改变的是那个变量的数据副本。然而,当您改变引用类型的数据时,您改变了数据,所有引用同一数据副本的变量都将对它们可见更改。

但是,由于 string 没有任何(没有反射技巧或不安全代码)可变字段或变异方法,您将永远无法使用 string 变量观察到此类变异。


1这里我指的是局部变量和字段。其他形式的赋值(例如属性)可以 运行 任意代码,因此它们当然可能有其他可见的副作用。