代码之家  ›  专栏  ›  技术社区  ›  Dinah SLaks

假装。NET字符串是值类型

  •  7
  • Dinah SLaks  · 技术社区  · 17 年前

    StringBuilder

    通过了解以下方面的价值参考区别,可以帮助或避免哪些现实世界场景。NET字符串与只是假装/误解它们是值类型?

    4 回复  |  直到 17 年前
        1
  •  17
  •   Abel    16 年前

    ……的设计 string s是故意的,作为一名程序员,你不需要太担心它。在许多情况下,这意味着你可以分配、移动、复制、更改字符串,而不必过多考虑如果存在对字符串的另一个引用并且会同时更改(就像对象引用一样)可能带来的复杂后果。

    方法调用中的字符串参数

    (编辑:本节稍后添加)
    当字符串传递给方法时,它们是通过引用传递的。当它们只在方法体中读取时,不会发生任何特殊情况。但是当它们被更改时,会创建一个副本,并在方法的其余部分中使用临时变量。此过程称为 .

    ref 关键字。这实际上允许更改字符串引用并将其返回给调用函数。如果不这样做,则无法通过方法体更改字符串:

    void ChangeBad(string s)      { s = "hello world"; }
    void ChangeGood(ref string s) { s = "hello world"; }
    
    // in calling method:
    string s1 = "hi";
    ChangeBad(s1);       // s1 remains "hi" on return, this is often confusing
    ChangeGood(ref s1);  // s1 changes to "hello world" on return
    

    StringBuilder 字符串构建器 可以忽略不计。警惕那些告诉你这些的程序员

    更多关于StringBuilder与字符串性能的内容

    • 具有许多小字符串附加的StringBuilder比字符串连接更快(30、50个附加),但在2秒内,即使是100%的性能提升也往往可以忽略不计(在某些罕见情况下是安全的);
    • 带有一些大字符串附加(80个字符或更大的字符串)的StringBuilder只有在数千次,有时是数十万次迭代后才能超过字符串连接,差异通常只有几个百分点;
    • + , StringBuilder.Append , String.Format , ToString 在这种情况下使用StringBuilder几乎永远不会有效。

    是

    在互联字符串上

    = 比较,或 Equals 不要玩 ReferenceEquals 在处理字符串时。

    关于String.Empty

    String.Empty :静态 字符串。空 总是被隔离的,但具有指定值的变量不是。但是,默认情况下,编译器将分配 字符串。空 并指向相同的存储器地址。结果:一个可变的字符串变量,与 引用相等

    // emptiness is treated differently:
    string empty1 = String.Empty;
    string empty2 = "";
    string nonEmpty1 = "something";
    string nonEmpty2 = "something";
    
    // yields false (debug) true (release)
    bool compareNonEmpty = object.ReferenceEquals(nonEmpty1, nonEmpty2);
    
    // yields true (debug) false (release, depends on .NET version and how it's assigned)
    bool compareEmpty = object.ReferenceEquals(empty1, empty2);
    

    深入

    你基本上问的是,新手会遇到什么情况。我认为我的观点归结为避免 object.ReferenceEquals 因为它与字符串一起使用时不可信。原因是当字符串在代码中是常量时使用字符串内部,但并不总是如此。你不能依赖这种行为。尽管 字符串。空 和 "" 总是处于中间状态,编译器认为值是可变的时候就不会了。不同的优化选项(调试与发布等)将产生不同的结果。

    做 你需要 引用相等 不管怎样?对于对象,它有意义,但对于字符串,它没有意义。教任何使用字符串的人避免使用它,除非他们也理解 unsafe 以及被钉住的物体。

    不 不可变的 using StringBuilder is not always the fastest approach .

    我在这里使用的很多信息都很详细 in this excellent article on strings ,以及用于就地操纵字符串(可变字符串)的“如何”。

    更新:
    更新:
    更新:
    更新: 增加了何时从字符串切换到字符串生成器的估计
    更新: 在Konrad Rudolph的评论之后,增加了一个关于StringBuilder与String性能的额外部分

        2
  •  3
  •   recursive    17 年前

    对于大多数代码来说,唯一真正重要的区别是 null

        3
  •  3
  •   Guffa    17 年前

        4
  •  1
  •   Community Mohan Dere    9 年前

    弦是一种特殊的品种。它们是引用类型,但大多数程序员仍将其用作值类型。通过使其不可变并使用内部池,它优化了内存使用,如果是纯值类型,内存使用量将很大。

    更多阅读:
    C# .NET String object is really by reference? on SO
    String.Intern Method on MSDN
    string (C# Reference) on MSDN

    更新:
    abel 对这篇文章的评论。它纠正了我的误导性陈述。

    推荐文章