pretending .NET字符串值类型类型、字符串值、pretending、NET

2023-09-03 11:22:50 作者:痴人说梦

在.NET中,字符串是不变的,是引用类型变量。这往往是作为一个惊喜,新的.NET开发人员谁可能误认为是值类型的对象,由于他们的行为。然而,除了使用的StringBuilder 长串联ESP的做法等。在循环中,没有任何理由在实践中,人们需要知道这种区别?

In .NET, strings are immutable and are reference type variables. This often comes as a surprise to newer .NET developers who may mistake them for value type objects due to their behavior. However, other than the practice of using StringBuilder for long concatenation esp. in loops, is there any reason in practice that one needs to know this distinction?

什么真实场景得到帮助或了解的价值参考的区别是关于.NET字符串避免主场迎战刚刚pretending /误解他们是值类型?

What real-world scenarios are helped or avoided by understanding the value-reference distinction with regard to .NET strings vs. just pretending/misunderstanding them to be value types?

推荐答案

字符串的设计 S为故意这样的,你应该不需要太担心它作为一个程序员。在许多情况下,这意味着你可以转让,移动,复制,修改字符串没有想得太多可能的复杂后果,如果另一个引用您的字符串存在,并会在同一时间被改变(与对象引用发生)。

The design of strings was deliberately such that you shouldn't need to worry too much about it as a programmer. In many situations, this means that you can just assign, move, copy, change strings without thinking too much of the possible intricate consequences if another reference to your string existed and would be changed at the same time (as happens with object references).

(编辑:本节后面加) 当字符串传递给方法,它们是通过引用传递。当他们是只读的方法体,什么都不会发生。但它们被改变时,一个副本被创建并临时变量被用在该方法的其余部分。这个过程被称为的复制上写的。

( this section added later) When strings are passed to a method, they are passed by reference. When they are only read in the method body, nothing special happens. But when they are changed, a copy is created and the temporary variable is used in the rest of the method. This process is called copy-on-write.

什么麻烦大三是,它们被用于这样的事实,对象是引用和它们在用于改变传递的参数的方法而改变。为了做同样的字符串,它们需要使用 REF 关键字。这实际上允许字符串参考被改变,并返回到调用函数。如果不这样做,该字符串不能用方法主体变了:

What troubles juniors is that they are used to the fact that objects are references and they are changed in a method which changes the passed parameter. To do the same with strings, they need to use the ref keyword. This actually allows the string reference to be changed and returned to the calling function. If you don't, the string cannot be changed by the method body:

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 可以忽略不计。警惕程序员告诉你的所有的字符串操作应该使用StringBuilder的做的。

On StringBuilder

This distinction is important, but beginner programmers are usually better off not knowing too much about it. Using StringBuilder when you do a lot of string "building" is good, but often, your application will have much more fish to fry and the little performance gain of StringBuilder is negligible. Be wary of programmers that tell you that all string manipulation should be done using StringBuilder.

作为一个经验非常粗略的规则:StringBuilder的有一定创作成本,但追加便宜。串有一个便宜的创作成本,但串联是相对昂贵的。 的转折点大约是400-500串联,视大小而定:在这之后,StringBuilder的变得更有效率的

As a very rough rule of thumb: StringBuilder has some creation cost, but appending is cheap. String has a cheap creation cost, but concatenation is relatively expensive. The turning point is around 400-500 concatenations, depending on size: after that, StringBuilder becomes more efficient.

编辑:基于从康拉德·鲁道夫评论,我说这节的

如果拇指previous规则,让你不知道,请考虑以下略为详细的解释:

If the previous rule of thumb makes you wonder, consider the following slightly more detailed explanations:

在StringBuilder的许多小字符串追加outruns字符串连接相当快(30,50追加),但在2微秒,甚至100%的性能提升通常是可以忽略不计(安全一些罕见的情况下); 在StringBuilder的一些大的字符串追加(80个字符以上的字符串)outruns字符串连接后,才几千,有时数千次迭代百分之不同的是往往只是百分之几; 混合字符串操作(替换,插入,子,正则表达式等),常使使用StringBuilder的或字符串连接相等; 常量字符串连接可以被优化掉的编译器,CLR或JIT,它不能为StringBuilder的; code经常混置 + StringBuilder.Append 字符串。格式的ToString 等字符串操作,在这种情况下使用StringBuilder的是几乎没有有效的。 StringBuilder with many small string appends outruns string concatenation rather quickly (30, 50 appends), but on 2µs, even 100% performance gain is often negligible (safe for some rare situations); StringBuilder with some large string appends (80 characters or larger strings) outruns string concatenation only after thousands, sometimes hundredths of thousands iterations and the difference is often just a few percents; Mixing string actions (replace, insert, substring, regex etc) often makes using StringBuilder or string concatenation equal; String concatenation of constants can be optimized away by the compiler, the CLR or the JIT, it can't for StringBuilder; Code often mixes concatenation +, StringBuilder.Append, String.Format, ToString and other string operations, using StringBuilder in such cases is hardly ever effective.

所以,当的是的是有效的?在许多小弦被追加的情况下,即,将数据序列化到一个文件中,例如,当你不需要改变写一次数据写入到StringBuilder的。而在情况下,很多方法需要附加的东西,因为StringBuilder的是引用类型,它们被改变时,字符串复制。

So, when is it efficient? In cases where many small strings are appended, i.e., to serialize data to a file, for instance and when you don't need to change the "written" data once "written" to StringBuilder. And in cases where many methods need to append something, because StringBuilder is a reference type and strings are copied when they are changed.

一个问题上升—不仅与初级程序员—当他们尝试做一个参考比较,发现,有时候结果是真实的,有时它是假的,在看似相同的情况。发生了什么?当琴弦分别由编译器拘禁并添加到全局静态实习串池,两个字符串之间的比较可以指向同一存储器地址。当(仅供参考!)比较两个字符串相等,一是实习和一个没有,就会产生错误。使用 = 比较或等于不要玩弄的ReferenceEquals 处理字符串时,

A problem rises — not only with junior programmers — when they try to do a reference comparison and find out that sometimes the result is true, and sometimes it is false, in seemingly the same situations. What happened? When the strings were interned by the compiler and added to the global static interned pool of strings, comparison between two strings can point to the same memory address. When (reference!)comparing two equal strings, one interned and one not, will yield false. Use = comparison, or Equals and do not play around with ReferenceEquals when dealing with strings.

在同一联赛中配合使用时,的String.Empty 有时会出现一个奇怪的现象:静态的String.Empty 总是实习,但是具有分配的值的变量则不是。然而,在默认情况下,编译器将分配的String.Empty 并指向相同的内存地址。结果:一个可变字符串变量,与的ReferenceEquals 相比,返回true,而你所期望的假,而不是

In the same league fits a strange behavior that sometimes occurs when using String.Empty: the static String.Empty is always interned, but a variable with an assigned value is not. However, by default the compiler will assign String.Empty and point to the same memory address. Result: a mutable string variable, when compared with ReferenceEquals, returns true, while you might expect false instead.

// 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);

在深度

vb.net中从字符串 到类型 Integer 的转换无效 搜狗问问

您基本上是问什么情况下可能发生的门外汉。我想我的观点可以归结为避免 object.ReferenceEquals ,因为与字符串中使用时,它不能被信任。其原因是,串实习时使用字符串是在code恒定,但并非总是如此。你不能依赖此行为。虽然的String.Empty 总是被拘留,这不是当编译器认为该值是可变的。不同的优化选项(调试VS释放和其他人)会产生不同的结果。

In depth

You basically asked about what situations can occur to the uninitiated. I think my point boils down to avoiding object.ReferenceEquals because it cannot be trusted when used with strings. The reason is that string interning is used when the string is constant in the code, but not always. You cannot rely on this behavior. Though String.Empty and "" are always interned, it is not when the compiler believes the value is changeable. Different optimization options (debug vs release and others) will yield different results.

在执行的需要的ReferenceEquals 呢?使用对象是有意义的,但字符串它没有。教任何人处理字符串,以避免它的使用,除非他们也明白不安全和固定的对象。

When do you need ReferenceEquals anyway? With objects it makes sense, but with strings it does not. Teach anybody working with strings to avoid its usage unless they also understand unsafe and pinned objects.

当性能是非常重要的,你可以发现,字符串实际上的没有的不可变的,那的使用的StringBuilder 是没有的始终是最快的方法。

When performance is important, you can find out that strings are actually not immutable and that using StringBuilder is not always the fastest approach.

很多我以前在这里的信息是详细的这个优秀的文章在串的,连同如何就地操作字符串(可变字符串)。

A lot of the information I used here is detailed in this excellent article on strings, along with a "how to" for manipulating string in-place (mutable strings).

更新:添加code样品 更新:添加深入部分(希望有人发现这很有用;) 更新:添加了一些链接,添加字符串PARAMS 节 更新:补充估计何时从字符串的StringBuilder |转换 更新:添加一个额外的部分上的StringBuilder VS字符串的性能,此言由康拉德·鲁道夫的

Update: added code sample Update: added 'in depth' section (hope someone find this useful ;) Update: added some links, added section on string params Update: added estimation for when to switch from strings to stringbuilder Update: added an extra section on StringBuilder vs String performance, after a remark by Konrad Rudolph