字符串实习?

发布于 2024-08-30 07:41:46 字数 747 浏览 4 评论 0原文

第二个 ReferenceEquals 调用返回 false。为什么 s4 中的字符串没有被保留? (我不关心 StringBuilder 相对于字符串连接的优势。)

string s1 = "tom";
string s2 = "tom";


Console.Write(object.ReferenceEquals(s2, s1)); //true

string s3 = "tom";
string s4 = "to";
s4 += "m";

Console.Write(object.ReferenceEquals(s3, s4)); //false

当我执行 String.Intern(s4); 时,我仍然得到 false。

这里,s3和s4都被实习了,但它们的引用不相等?

string s3 = "tom";
string s4 = "to";
s4 += "m";
String.Intern(s4);

Console.WriteLine(s3 == s4); //true
Console.WriteLine(object.ReferenceEquals(s3, s4)); //false
Console.WriteLine(string.IsInterned(s3) != null);  //true (s3 is interned)
Console.WriteLine(string.IsInterned(s4) != null);  //true (s4 is interned)

The second ReferenceEquals call returns false. Why isn't the string in s4 interned? (I don't care about the advantages of StringBuilder over string concatenation.)

string s1 = "tom";
string s2 = "tom";


Console.Write(object.ReferenceEquals(s2, s1)); //true

string s3 = "tom";
string s4 = "to";
s4 += "m";

Console.Write(object.ReferenceEquals(s3, s4)); //false

When I do String.Intern(s4);, I still get false.

Here, both s3 and s4 are interned but their references are not equal?

string s3 = "tom";
string s4 = "to";
s4 += "m";
String.Intern(s4);

Console.WriteLine(s3 == s4); //true
Console.WriteLine(object.ReferenceEquals(s3, s4)); //false
Console.WriteLine(string.IsInterned(s3) != null);  //true (s3 is interned)
Console.WriteLine(string.IsInterned(s4) != null);  //true (s4 is interned)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

寄离 2024-09-06 07:41:46

s4 中的字符串被保留。但是,当您执行 s4 += "m"; 时,您创建了一个新字符串,该字符串不会被保留,因为它的值不是字符串文字,而是字符串连接操作的结果。因此,s3s4 是两个不同内存位置中的两个不同字符串实例。

有关字符串驻留的详细信息,请查看此处,特别是在最后一个例子中。当您执行String.Intern(s4)时,您确实正在实习该字符串,但您仍然没有在这两个实习字符串之间执行引用相等性测试。 String.Intern 方法返回暂留字符串,因此您需要执行以下操作:

string s1 = "tom";
string s2 = "tom";

Console.Write(object.ReferenceEquals(s2, s1)); //true 

string s3 = "tom";
string s4 = "to";
s4 += "m";

Console.Write(object.ReferenceEquals(s3, s4)); //false

string s5 = String.Intern(s4);

Console.Write(object.ReferenceEquals(s3, s5)); //true

The string in s4 is interned. However, when you execute s4 += "m";, you have created a new string that will not be interned as its value is not a string literal but the result of a string concatenation operation. As a result, s3 and s4 are two different string instances in two different memory locations.

For more information on string interning, look here, specifically at the last example. When you do String.Intern(s4), you are indeed interning the string, but you are still not performing a reference equality test between those two interned strings. The String.Intern method returns the interned string, so you would need to do this:

string s1 = "tom";
string s2 = "tom";

Console.Write(object.ReferenceEquals(s2, s1)); //true 

string s3 = "tom";
string s4 = "to";
s4 += "m";

Console.Write(object.ReferenceEquals(s3, s4)); //false

string s5 = String.Intern(s4);

Console.Write(object.ReferenceEquals(s3, s5)); //true
晨光如昨 2024-09-06 07:41:46

字符串是不可变的。这意味着它们的内容无法更改。

当您在内部执行 s4 += "m"; 时,CLR 会将字符串复制到内存中的另一个位置,其中包含原始字符串和附加部分。

请参阅 MSDN 字符串参考

Strings are immutable. This means their contents can't be changed.

When you do s4 += "m"; internally, the CLR copies the string to another location in memory which contains the original string and the appended part.

See MSDN string reference.

青瓷清茶倾城歌 2024-09-06 07:41:46

来源:https://blogs .msdn.microsoft.com/ericlippert/2009/09/28/string-interning-and-string-empty/

字符串驻留是编译器的一种优化技术。如果一个编译单元中有两个相同的字符串文字,则生成的代码可确保程序集中仅为该文字的所有实例(用双引号括起来的字符)创建一个字符串对象。

我来自 C# 背景,所以我可以通过给出一个例子来解释:

object obj = "Int32";
string str1 = "Int32";
string str2 = typeof(int).Name;

以下比较的输出:

Console.WriteLine(obj == str1); // true
Console.WriteLine(str1 == str2); // true    
Console.WriteLine(obj == str2); // false !?

Note1:对象通过引用进行比较。

注2:typeof(int).Name 通过反射方法求值,因此在编译时不会求值。 这里这些比较是在编译时进行的。

结果分析:
1) true,因为它们都包含相同的文字,因此生成的代码将只有一个引用“Int32”的对象。 参见注释 1

2) true,因为检查两个值的内容是否相同。

3) FALSE,因为 str2 和 obj 没有相同的文字。请参阅注释 2

Source: https://blogs.msdn.microsoft.com/ericlippert/2009/09/28/string-interning-and-string-empty/

String interning is an optimization technique by the compiler. If you have two identical string literals in one compilation unit then the code generated ensures that there is only one string object created for all the instance of that literal(characters enclosed in double quotes) within the assembly.

I am from C# background, so i can explain by giving a example from that:

object obj = "Int32";
string str1 = "Int32";
string str2 = typeof(int).Name;

output of the following comparisons:

Console.WriteLine(obj == str1); // true
Console.WriteLine(str1 == str2); // true    
Console.WriteLine(obj == str2); // false !?

Note1:Objects are compared by reference.

Note2:typeof(int).Name is evaluated by reflection method so it does not gets evaluated at compile time. Here these comparisons are made at compile time.

Analysis of the Results:
1) true because they both contain same literal and so the code generated will have only one object referencing "Int32". See Note 1.

2) true because the content of both the value is checked which is same.

3) FALSE because str2 and obj does not have the same literal. See Note 2.

傾旎 2024-09-06 07:41:46

首先,到目前为止,关于不可变字符串的所有内容都是正确的。但还有一些重要的事情没有写出来。代码

string s1 = "tom";
string s2 = "tom";
Console.Write(object.ReferenceEquals(s2, s1)); //true

显示确实为“True”,但只是因为一些小的编译器优化,或者像这里一样,因为 CLR 忽略 C# 编译器属性(请参阅“CLR via C#”一书)并仅在其中放置一个字符串 "tom"堆。

其次,您可以使用以下几行修复这种情况:

s3 = String.Intern(s3);
s4 = String.Intern(s4);
Console.Write (object.ReferenceEquals (s3, s4)); //true

函数 String.Intern 计算字符串的哈希码并在内部哈希表中搜索相同的哈希值。因为它找到了这个,所以它返回对已经存在的 String 对象的引用。如果内部哈希表中不存在该字符串,则会创建该字符串的副本并计算哈希值。垃圾收集器不会为字符串释放内存,因为它是由哈希表引用的。

First of all, everything written so far about immutable strings is correct. But there are some important things which are not written. The code

string s1 = "tom";
string s2 = "tom";
Console.Write(object.ReferenceEquals(s2, s1)); //true

display really "True", but only because of some small compiler optimization or like here because CLR ignore C# compiler attributes (see "CLR via C#" book) and place only one string "tom" in the heap.

Second you can fix the situation with following lines:

s3 = String.Intern(s3);
s4 = String.Intern(s4);
Console.Write (object.ReferenceEquals (s3, s4)); //true

Function String.Intern calculates a hash code of the string and search for the same hash in the internal hash table. Because it find this, it returns back the reference to already existing String object. If the string doesn't exist in the internal hash table, a copy of the string is made and the hash computed. The garbage collector doesn't free memory for the string, because it is referenced by the hash table.

塔塔猫 2024-09-06 07:41:46

在 C# 中,每个字符串都是一个不同的对象,并且无法编辑。您正在创建对它们的引用,但每个字符串都是不同的。该行为是一致且易于理解的。

我是否可以建议检查 StringBuilder 类来操作字符串而不创建新实例?对于您想要用字符串做的任何事情来说它应该足够了。

In C#, each string is a distinct object, and cannot be edited. You are creating references to them, but each string is distinct. The behaviour is consistent and easy to understand.

Might I suggest examining the StringBuilder class for manipulating strings without creating new instances? It should be sufficient for anything you want to do with strings.

寻找一个思念的角度 2024-09-06 07:41:46

当比较两个对象而不是字符串时,不会调用字符串相等运算符,因为它是没有多态性的静态方法。

这是一个测试:

static void Test()
{
  object o1 = "a";
  object o2 = new string("a".ToCharArray());

  string o3 = "a";
  string o4 = new string("a".ToCharArray());

  object o5 = "a"; // Compiler optimization addr(o5) = addr(o6)
  object o6 = "a";

  string o7 = "a"; // Compiler optimization addr(o7) = addr(o8)
  string o8 = "a";

  Console.WriteLine("Enter same text 4 times:");

  object o9 = Console.ReadLine();
  object o10 = Console.ReadLine();

  string o11 = Console.ReadLine();
  string o12 = Console.ReadLine();

  Console.WriteLine("object arr   o1  == o2  ? " + ( o1 == o2 ).ToString());
  Console.WriteLine("string arr   o3  == o4  ? " + ( o3 == o4 ).ToString());
  Console.WriteLine("object const o5  == o6  ? " + ( o5 == o6 ).ToString());
  Console.WriteLine("string const o7  == o8  ? " + ( o7 == o8 ).ToString());
  Console.WriteLine("object cnsl  o9  == o10 ? " + ( o9 == o10 ).ToString());
  Console.WriteLine("string cnsl  o11 == o12 ? " + ( o11 == o12 ).ToString());
  Console.WriteLine("o1.Equals(o2) ? " + o1.Equals(o2).ToString());
  Console.WriteLine("o3.Equals(o4) ? " + o3.Equals(o4).ToString());
  Console.WriteLine("o5.Equals(o6) ? " + o5.Equals(o6).ToString());
  Console.WriteLine("o7.Equals(o8) ? " + o7.Equals(o8).ToString());
  Console.WriteLine("o9.Equals(o10) ? " + o9.Equals(o11).ToString());
  Console.WriteLine("o11.Equals(o12) ? " + o11.Equals(o12).ToString());
}

结果:

object arr   o1  == o2  ? False
string arr   o3  == o4  ? True
object const o5  == o6  ? True
string const o7  == o8  ? True
object cnsl  o9  == o10 ? False
string cnsl  o11 == o12 ? True
o1.Equals(o2) ? True
o3.Equals(o4) ? True
o5.Equals(o6) ? True
o7.Equals(o8) ? True
o9.Equals(o10) ? True
o11.Equals(o12) ? True

https://referencesource.microsoft.com/#mscorlib /system/string.cs

When comparing two objects, not strings, the string equality operator is not called since it is static method without polymorphism.

Here is a test:

static void Test()
{
  object o1 = "a";
  object o2 = new string("a".ToCharArray());

  string o3 = "a";
  string o4 = new string("a".ToCharArray());

  object o5 = "a"; // Compiler optimization addr(o5) = addr(o6)
  object o6 = "a";

  string o7 = "a"; // Compiler optimization addr(o7) = addr(o8)
  string o8 = "a";

  Console.WriteLine("Enter same text 4 times:");

  object o9 = Console.ReadLine();
  object o10 = Console.ReadLine();

  string o11 = Console.ReadLine();
  string o12 = Console.ReadLine();

  Console.WriteLine("object arr   o1  == o2  ? " + ( o1 == o2 ).ToString());
  Console.WriteLine("string arr   o3  == o4  ? " + ( o3 == o4 ).ToString());
  Console.WriteLine("object const o5  == o6  ? " + ( o5 == o6 ).ToString());
  Console.WriteLine("string const o7  == o8  ? " + ( o7 == o8 ).ToString());
  Console.WriteLine("object cnsl  o9  == o10 ? " + ( o9 == o10 ).ToString());
  Console.WriteLine("string cnsl  o11 == o12 ? " + ( o11 == o12 ).ToString());
  Console.WriteLine("o1.Equals(o2) ? " + o1.Equals(o2).ToString());
  Console.WriteLine("o3.Equals(o4) ? " + o3.Equals(o4).ToString());
  Console.WriteLine("o5.Equals(o6) ? " + o5.Equals(o6).ToString());
  Console.WriteLine("o7.Equals(o8) ? " + o7.Equals(o8).ToString());
  Console.WriteLine("o9.Equals(o10) ? " + o9.Equals(o11).ToString());
  Console.WriteLine("o11.Equals(o12) ? " + o11.Equals(o12).ToString());
}

Results:

object arr   o1  == o2  ? False
string arr   o3  == o4  ? True
object const o5  == o6  ? True
string const o7  == o8  ? True
object cnsl  o9  == o10 ? False
string cnsl  o11 == o12 ? True
o1.Equals(o2) ? True
o3.Equals(o4) ? True
o5.Equals(o6) ? True
o7.Equals(o8) ? True
o9.Equals(o10) ? True
o11.Equals(o12) ? True

https://referencesource.microsoft.com/#mscorlib/system/string.cs

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文