为什么String是值类型,虽然它是一个类而不是结构?

11 c# string types reference value-type

请看以下示例:

string me = "Ibraheem";
string copy = me;
me = "Empty";
Console.WriteLine(me);
Console.WriteLine(copy);
Run Code Online (Sandbox Code Playgroud)

输出是:

Empty
Ibraheem
Run Code Online (Sandbox Code Playgroud)

由于它是类类型(即不是结构),String copy也应该包含Empty因为= operatorin C#分配对象的引用而不是对象本身(如在C++中)?

Ada*_*son 18

虽然接受的答案解决了这个问题(和其他一些问题一样),但我想给出一个专门针对你实际问的内容的答案,这是关于变量赋值的语义.

C#中的变量只是用于保存单个值的内存块.重要的是要注意,没有"值变量"和"引用变量"这样的东西,因为变量只保存值.

"值"和"参考"之间的区别来自类型.值类型(VT)表示整个数据存储在变量中.

如果我有一个名为的整数变量abc保存该值100,那么这意味着我的应用程序中有一个四字节的内存块,用于存储其中的文字值100.这是因为int是一种值类型,因此所有数据都存储在变量中.

另一方面,如果我有一个string名为的变量foo保存该值"Adam",则涉及两个实际的内存位置.第一个是存储实际字符的内存,"Adam"以及有关我的字符串的其他信息(长度等).然后将对此位置的引用存储在我的变量中.引用与C/C++中的指针非常相似; 虽然它们不一样,但这种解释足以说明这一点.

因此,总而言之,引用类型的值是内存中另一个位置的引用,其中值类型的值是数据本身.

当你为变量赋值时,你所改变的只是变量的.如果我有这个:

string str1 = "foo";
string str2 = str1;
Run Code Online (Sandbox Code Playgroud)

然后我有两个字符串变量保持相同的值(在这种情况下,它们每个都持有对同一个字符串的引用,"foo".)如果那么这样做:

str1 = "bar";
Run Code Online (Sandbox Code Playgroud)

然后我将值更改str1为对字符串的引用"bar".这根本不会改变str2,因为它的值仍然是对字符串的引用"foo".

  • +1我更喜欢这个答案,因为它实际上清除了像我这样的ac #startner的概念混乱(2年c#) (3认同)

Ant*_*ram 9

System.String不是值类型.它具有一些行为类似于值类型,但你所遇到的行为是不是其中之一.请考虑以下代码.

class Foo 
{ 
     public string SomeProperty { get; private set; }
     public Foo(string bar) { SomeProperty = bar } 
}

Foo someOtherFoo = new Foo("B");
Foo foo = someOtherFoo;
someOtherFoo = new Foo("C");
Run Code Online (Sandbox Code Playgroud)

如果您检查了输出foo.SomeProperty,您认为它是否相同someOtherFoo.SomeProperty?如果是这样,你对语言的理解有缺陷.

在您的示例中,您为字符串指定了值.而已.它与值类型,引用类型,类或结构无关.这是一个简单的任务,无论你是在谈论字符串,长篇还是Foos,都是如此.您的变量暂时包含相同的值(对字符串"Ibraheem"的引用),但之后您重新分配了其中一个.这些变量并非始终存在着千丝万缕的联系,它们只是暂时有一些共同点.

  • 如果他对这个例子感到困惑,我们都会敬酒. (3认同)
  • @DDDD如果缺少`new`关键字让你困惑,可以认为``Empty``可以被认为是`new string("Empty")`的一个捷径(概念上,`new string("Empty") ")`实际上不会编译,因为它不是`string`的构造函数之一) (3认同)
  • @先生.DDD:*C#中的变量是用于存储值的一部分内存.*Value*types*(结构和原始类型)直接存储在变量中,而引用类型存储在其他地方,*reference*存储在该变量中location是变量中的值.为变量赋值*值*(无论该值是引用,基本类型还是结构)时,它不会影响任何其他内存位置.在你的例子中,`copy`和`me`是两个完全不同的变量(因此存储器位置)恰好在某个点上具有相同的*值*. (2认同)

Dan*_*ite 8

它不是值类型.当您使用字符串文字时,它实际上是编译时存储的引用.因此,当您分配字符串时,您基本上就像在C++中一样更改指针.

  • @DrDDDD不是.所有类都以这种方式表现.重新分配引用时,只有此引用会更改,而不会更改. (4认同)

Kon*_*lph 6

字符串的行为与任何其他类相同.考虑:

class Test {
    public int SomeValue { get; set; }
    public Test(int someValue) { this.SomeValue = someValue; }
}

Test x = new Test(42);
Test y = x;
x = new Test(23);
Console.WriteLine(x.SomeValue + " " + y.SomeValue);
Run Code Online (Sandbox Code Playgroud)

输出:

23 42
Run Code Online (Sandbox Code Playgroud)

- 与string示例中的行为完全相同.