字符串的作用类似于值类型
本文关键字:类型 类似于 作用 字符串 | 更新日期: 2023-09-27 17:57:03
string
是引用类型,但行为类似于值类型。
string a,b;
a=b="test"; //As i understood a and b have to point to the same location in the heap
a="a";
Console.WriteLine("a: {0}, b: {1}",a,b);
结果它打印 a: a, b: 测试请解释为什么对a
所做的更改不会反映在b
上,因为根据参考类型规则可以预期。
您没有更改对象a
指向,您只是更改变量a
。这对于字符串来说也不是特别的,你可以对任何类型执行此操作并获得完全相同的行为。
class Foo
{
private int _i;
public Foo(int i)
{
_i = i;
}
public override string ToString()
{
return _i.ToString();
}
}
Foo a, b;
a=b= new Foo(1);
a=new Foo(2);
Console.WriteLine("a: {0}, b: {1}",a,b);
请参阅我对这个问题的回答,我深入类比变量和它们指向的对象之间的差异。
因为您没有更改a
指向的值 - 所以您更改了引用本身。例如,这与 C 中的相同 - 不要想象a = "Hi"
正在改变*a
.
事实上,在不安全的代码之外,无法更改现有字符串。.NET 中的字符串是不可变的。你只会创建新的字符串或更改引用,这意味着,实际上,string
具有值语义,就像任何其他不可变的数据类型一样。这是一个设计选择 - 字符串很硬,这使得它们更简单。
赋值运算符在 C# 中不可重写 - 它始终表示"为标识符赋值"。在 string
的情况下,值是对字符串的引用,而不是字符串本身。但是,更改一个本地中的引用不会更改其他本地中的引用。怎么会?它不是指向指针的指针。
让我们更好地说明引用类型和值类型之间的区别:
void Main()
{
A a = default(A), b = default(A);
a = b = new A { Number = 42 };
a.Number = 10;
Console.WriteLine(a); // 42
Console.WriteLine(b); // 10
}
public struct A
{
public int Number;
}
现在,A 是一个值类型,所以当我们将b
分配给 a
时,我们实际上会制作一个副本。两个局部变量不指向同一对象。因此,当a.Number
更改为 10 时,b.Number
保持 42。
但是,如果将声明更改为 public class A
,则赋值仅更改引用的值 - 换句话说,仅存在一个A
实例。然后,a.Number = 10
实际上也会更改b.Number
- 两者在内存中的位置相同。
如果将其与 C 进行比较,就好像值类型局部是值本身,而引用类型局部是指向值的指针。所以,像这样:
// Value-type
A a, b;
b.Number = 42;
a = b;
a.Number = 10; // Only the value in a is changed
// Reference-type
A *a, *b;
a = b = new A(42);
a->Number = 10; // Both locals point to the changed value
这与C++引用的工作方式完全不同 - 在 C# 中,这些引用仅限于方法参数。因此,例如,C# 中的交换方法如下所示:
void Main()
{
int a = 42, b = 10;
Swap(ref a, ref b);
Console.WriteLine(a); // 10
Console.WriteLine(b); // 42
}
public void Swap(ref int a, ref int b)
{
int x = 0;
SwapI(ref a, ref b, ref x);
}
// No ref locals, so we need a helper method
private void SwapI(ref int a, ref int b, ref int x)
{
x = a;
a = b;
b = x;
}
由于我们要切换的参数是ref
的,因此无论类型是值类型还是引用类型,它们始终具有引用语义。
//你初始化了变量 - 太好了!
字符串 a,b;
/a="test" 和 b="test"
a=b="测试";
/现在 a="a" 和 b 仍然是 "test"
a="a";
要让 b 显示为"a",您必须将其设置为"a"。设置变量的唯一方法是在变量位于左侧的位置进行声明。因此,要使b等于"a",您必须执行以下操作:
b=a;在最后一行之后。所以你的 3 行看起来像这样:
a=b="测试";
a="a";
新行
b=a;
现在,当您键入 Console.WriteLine("a: {0}, b: {1}",a,b);
你得到 A: A, B: A