以下是我上一次采访的方式:
问题:字符串存储在哪里?
答案:堆,因为它是引用类型
问题:请解释以下代码:
static void Main(string[] args)
{
string one = "test";
string two = one;
one = one + " string";
Console.WriteLine("One is {0}" , one);
Console.WriteLine("Two is {0}", two);
}
答案:画了两张如下图:
(代表声明,string two = one;
(表示语句one = one + " string";
。在堆上创建一个新字符串并分配)
问题:正确。为下面的代码片段绘制类似的内容:
class Program
{
static void Main(string[] args)
{
Test one = new Test { someString = "test" };
Test two = one;
one.someString = "test String";
Console.WriteLine("One is {0}", one.someString);
Console.WriteLine("Two is {0}", two.someString);
}
}
class Test
{
public string someString { get; set; }
}
答案:
[Test two = one
]
one.someString = "test String";
问题:好的。您说strings
和classes
都是引用类型。那么为什么创建一个新的字符串对象并赋值,而对于类,现有的字符串属性本身会被修改?
答案:因为字符串是不可变的,而类是可变的。
(虽然我清除了采访,但我仍然不明白这种行为。为什么班级的设计师在保持字符串不可变的同时使其变得可变?到处都有很多热情的答案,但任何人都可以通过解释来简化上述代码的这种特殊行为?)
答案 0 :(得分:4)
字符串变为不可变的原因之一,即使它们是引用类型,也是为了使它们看起来和行为像原始类型(例如,int,double,float)。
这也是字符串是唯一可以表示为文字的引用类型(例如"some string"
)的原因。许多其他语言采用相同的方法,例如Java。
答案 1 :(得分:3)
字符串是不可变的,因为从逻辑上讲,它们是单个值,并且可变性会导致许多意外行为。
但是,字符串不值 types ,因为它们往往会传递很多,这需要大量复制值。这将变得非常昂贵,特别是对于大字符串。
因此,为了充分利用这两个世界,.Net中的字符串是引用类型,但也是不可变的。
答案 2 :(得分:1)
命令one = ...
将名为 one
的* 指针设置为新值。由于two
是一个不同的指针,因此它保留了它的原始值。
命令one.someString = ...
修改 one
引用的对象。 two
仍然是一个不同的指针,但由于它指向同一个对象,因此它们之间共享修改。
答案 3 :(得分:0)
字符串共享缓冲区。在你的情况下,如果一个和两个是字符串,它们将是单独的对象(堆上的两个对象),但在内部它们将指向相同的缓冲区(堆上的第三个对象)。