string是不可变的,stringbuilder是可变的

时间:2009-03-20 09:42:03

标签: .net

任何人都可以用例子解释


相关讨论: Most efficient way to concatenate strings?

8 个答案:

答案 0 :(得分:16)

string s = "a";

s += "b"; // this will create a new string object

StringBuilder sb = new StringBuild();
sb.Append("a");
sb.Append("b"); // appends to existing StringBuilder

答案 1 :(得分:7)

您无法编辑字符串的值,字符串对象的每个方法都返回一个新字符串而不是更改原始字符串。另一方面,StringBuilder可以改变它的内容(例如添加新字符串)。

string original = "the brown fox jumped over the lazy dog";
string altered = original.Insert(original.IndexOf("fox"), "cat");
// altered = the brown cat jumped over the lazy dog

除非您创建新字符串,否则无法更改原始字符串的内容,或者将实例重新引用到另一个字符串对象。

答案 2 :(得分:4)

即使是一个老问题,我还是会回答。

字符串(引用类型存储)

将字符串的值放在托管堆上,并使用指针指向它。如果更改字符串的值,则新值将存储在托管堆上的另一个位置,并且指针将更改为指向新位置。旧值保留在堆上,没有指向其位置的任何指针。最终可能会耗尽堆内存。

这是一项安全保障措施。它确保除非程序员在物理上改变字符串(实际上在堆栈上添加新值并更改指针),否则系统不能更改字符串。我认为没有办法将指针从堆上的新值更改为堆上的旧值。


2010年10月20日编辑

  

StringBuilder(值类型存储)<<<不正确

     

不使用托管堆,和   因此,不使用指针   值。它创造了一个价值   单一地点。价值在那   可以操纵单个位置   许多不同的方式。

StringBuilder(引用类型存储)

将对象放在托管堆上,并使用指针指向它。该值通过指针放置在对象中。可以通过指针操纵该值。我认为这意味着如果更改了值,则会分配堆上的地址空间以适应值的扩展或收缩。


权衡

Stringbuilder使用的处理时间可以忽略不计,存储[在堆上]的内存更少,并且其值可以按字节操作。

String使用的处理时间可以忽略不计,并且存储空间更多,因为它不能更改旧值,也不能处理它们。为字符串分配新值只是将指针指向堆上的另一个位置,并将新值存储在那里。旧值永远留在堆上,没有指针。

参考类型存储和值类型存储的比较。

alt text

经验法则

  • System.ValueType中的任何内容都是值类型。
  • system.ValueType之外的任何内容,都是引用类型。

最后,有一篇文章显示some code tests to prove these points

答案 3 :(得分:3)

在C ++中你可以这样做:

std::string hello = "Hello, world!\r\n";
hello[7] = 'W';

在C#中,你无法做到这一点。字符串无法更改。

答案 4 :(得分:3)

字符串对象是不可变的,一旦创建,就无法更改

string str;
//new string object constructed. str= new string("string1");
str="string1";
//again new object will be constructed str=new string("string1string2");
str=str+"string2" 
since a new object is created for every assignment, there is an overhead.

但是,字符串构建器类提供了一种有效的方法来重复将字符串的位附加到已构造的对象。

StringBuilder str=new StringBuilder();
str.Append("string1");
str.Append("string2");

性能差异太小,无法在较少的分配和连接操作上进行比较,但如果我们有更多的字符串操作,则通过从字符串切换到字符串构建器可以获得显着的性能提升。

答案 5 :(得分:1)

为什么它们变得不可变的一些原因:

  • 不可变类型是线程安全的 意思是你可以传递一个字符串 不用担心它已被改变。
  • 安全性更令人担忧 字符串可以更改。

答案 6 :(得分:0)

字符串是不可变的,

这意味着我们无法在声明后更改字符串。

字符串构建器是可变的

这是可以执行的变种操作。我们可以改变字符串..

答案 7 :(得分:0)

字符串的不变性[实例是只读]

    string s="hi";
    //now let s be address 1000
    s+=" there"; 
    //above concatination causes creation of new instance in address location other than 1000
    //with modified value "hi there"

stringbuilder的可变性[实例可以修改]

    StringBuilder sbr = new StringBuilder("My Favourite Programming Font is ");
    sbr.Append("Inconsolata")
//append operation only modifies existing instance of sbr rather than creating new instance

更多有趣的示例和详细讨论强烈建议您关注this link

String Vs StringBuilder

  • 字符串
    1. 系统命名空间下的
    2. 不可变(只读)实例
    3. 当值发生连续变化时,性能会下降
    4. 线程安全
    5. StringBuilder(可变字符串)
      1. 在System.Text命名空间
      2. 可变实例
      3. 显示更好的性能,因为对现有实例进行了新的更改
  

关于此主题的描述性文章,其中包含大量示例   ObjectIDGenerator,请关注this link

     

相关Stackeoverflow问题:Mutability of string when string doesn't change in C#?