为什么字符串类型表现得像值类型?
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这里我指的是局部变量和字段。其他形式的赋值(例如属性)可以 运行 任意代码,因此它们当然可能有其他可见的副作用。
我对引用的类型感到非常困惑。搜索了一下,发现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这里我指的是局部变量和字段。其他形式的赋值(例如属性)可以 运行 任意代码,因此它们当然可能有其他可见的副作用。