string的作用类似于值类型

时间:2016-07-14 16:32:05

标签: c# string types reference

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:test 请解释为什么对a所做的更改未反映在b上,因为根据参考类型规则可以预期。

3 个答案:

答案 0 :(得分:3)

您没有更改对象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);

请参阅我对this question的回答,我深入研究了变量与他们指向的对象之间的差异。

答案 1 :(得分:1)

因为您没有更改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,因此它们总是具有引用语义,无论类型是值类型还是引用类型。

答案 2 :(得分:0)

//你把变量搞砸了 - 太棒了!
字符串a,b;

// a =“测试” b =“测试”
A = B = “测试”;

//现在 a =“a” b 仍然“测试”
一个= “A”;

要让b显示为“a”,您必须将其设置为“a”。设置变量的唯一方法是在变量位于左侧的位置进行声明。因此,为了使b等于“a”,你必须做这样的事情:
在你的最后一行之后 b = a; 。所以你的3行看起来像这样:

A = B = “测试”;
一个= “A”;
//新行
B = A;
现在键入Console.WriteLine(“a:{0},b:{1}”,a,b); 你得到 a:a,b:a