字符串的作用类似于值类型

本文关键字:类型 类似于 作用 字符串 | 更新日期: 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