我读了Jon Skeet的测验,我想知道为什么我的第二个样本在第一个样本时不起作用.
为什么这会产生true:
object x = new string("".ToArray());
object y = new string("".ToArray());
Console.WriteLine(x == y); //true
Run Code Online (Sandbox Code Playgroud)
但是这个没有:
var k="k";
//string.intern(k); // doesn't help
object x = new string(k.ToArray());
object y = new string(k.ToArray());
Console.WriteLine(x == y); //false
Run Code Online (Sandbox Code Playgroud)
我在vs2010上使用fw 4.5.
幸运的是我也安装了vs2005,结果相同:

Mar*_*zek 43
这是Eric Lippert撰写的一篇博文,回答了你的问题:String interning和String.Empty.
他描述了类似的情况:
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 !?
Run Code Online (Sandbox Code Playgroud)
所以这个想法是,实习并不意味着你只有一个特定的实例string,即使它是实习的.默认情况下,只会编译时间文字.这意味着以下代码打印为true:
var k1 = "k";
object k2 = "k";
Console.WriteLine(k1 == k2);
Run Code Online (Sandbox Code Playgroud)
但是,如果您尝试"k"在运行时以编程方式创建包含内容的字符串,例如使用string(char[])构造函数,调用ToString()对象,使用StringBuilder等,则默认情况下您将不会获得实例化字符串.这个打印假;
var k1 = "k";
object k2 = new string("k".ToCharArray());
Console.WriteLine(k1 == k2);
Run Code Online (Sandbox Code Playgroud)
为什么?因为运行时的实习字符串很昂贵.
没有免费午餐这样的事情.
(......)
简而言之,在一般情况下,不值得实习所有字符串.
关于空字符串的不同行为:
某些版本的.NET运行时会在运行时自动实现空字符串,有些则不会!
Ben*_*enM 11
需要注意的是实习的新的代码的第二块串并让他们平等的.
var k="k";
object x = string.Intern(new string(k.ToArray()));
object y = string.Intern(new string(k.ToArray()));
Console.WriteLine(x == y); //true
Run Code Online (Sandbox Code Playgroud)
看起来它是自动实现空字符串,但非空字符串不会被实现,除非它们是明确地完成的(或者它们是始终被实现的文字字符串).
我猜是的,空字符串被视为特殊情况并被自动实现,可能是因为检查是如此微不足道,以至于它不会增加任何实际的性能损失(我们可以肯定地说,任何长度为0的字符串都是空字符串并且与任何其他空字符串相同 - 所有其他字符串都要求我们查看字符而不仅仅是长度.
第一种情况比较了对同一对象(String.Empty)的2个引用.调用operator==2个object变量会导致它们通过引用进行比较并给出true.
第二种情况产生2个不同的字符串类实例.他们的参考比较给出false
如果你给string类型x和y第二种情况,string.operator==将调用覆盖并进行比较true
请注意,在这两种情况下,我们都不直接处理字符串实习.我们比较的字符串对象是使用string(char[])构造函数创建的.显然,构造函数被设计为string.Empty在使用空数组作为参数调用时返回字段的值.
MarcinJuraszek发布的答案引用了Lippert的博客,该博客讨论了字符串实习.该博客文章讨论了字符串类使用的其他角落案例.考虑前面提到的Lippert博客中的这个例子:
object obj = "";
string str1 = "";
string str2 = String.Empty;
Console.WriteLine(obj == str1); // true
Console.WriteLine(str1 == str2); // true
Console.WriteLine(obj == str2); // sometimes true, sometimes false?!
Run Code Online (Sandbox Code Playgroud)
我们在这里看到的是,空字符串literal("")的赋值不能保证产生对静态只读System.String.Empty字段的引用.
让我们看看IL的object x = new string("".ToArray());表达式:
IL_0001: ldstr ""
IL_0006: call !!0[] [System.Core]System.Linq.Enumerable::ToArray<char>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)
IL_000b: newobj instance void [mscorlib]System.String::.ctor(char[])
IL_0010: stloc.0
Run Code Online (Sandbox Code Playgroud)
实习可能(或可能不)发生在IL_0001线上.无论文本是否被实习,该ToArray()方法都会产生一个新的空数组,并String::.ctor(char[])给出了我们的信息String.Empty.
我们在这里看到的并不是特殊情况,string.Empty而是同时string作为引用类型和不可变类的类的副作用之一.还有其他不可变的框架类型,它们具有类似语义的预定义值(如DateTime.MinValue).但据我所知,这样的框架类型被定义为struct与string引用类型不同.值类型是完全不同的故事......从可变类构造函数返回一些固定的预定义类型实例是没有意义的(调用代码将能够更改该实例并导致该类型的不可预测的行为).因此,如果这些类型是不可变的,那么构造函数不总是返回新实例的引用类型可能存在.我不知道框架中的其他类型,除了string.
| 归档时间: |
|
| 查看次数: |
2404 次 |
| 最近记录: |