来自 Richter 和 this discussion ,我希望任何两个“相同”的字符串都是相同的引用。但就在 LINQPad 中,我在这个主题上得到了不同的结果。这是代码:
void Main()
{
string alpha = String.Format("Hello{0}", 5);
string brava = String.Format("Hello{0}", 5);
ReferenceEquals(alpha, brava).Dump();
String.IsInterned(alpha).Dump();
String.IsInterned(brava).Dump();
alpha = "hello";
brava = "hello";
ReferenceEquals(alpha, brava).Dump();
}
下面是 Dump() 调用的结果:
False
Hello5
Hello5
True
我希望第一个和最后一个 ReferenceEquals
都为 True
。发生了什么事?
除了上面的例子,在其他什么情况下 ReferenceEquals 会失败?比如多线程?
这个问题很重要,例如,如果我使用传递到方法中的字符串参数作为获取锁的对象。在那种情况下,引用最好是相同的!!!
最佳答案
字符串驻留不会发生在动态创建的字符串上。这包括由 String.Format 和 StringBuilder 创建的那些(我相信 String.Format 在内部使用 StringBuilder)。 MSDN 的 String.Intern 文档表明这一点:
In the following example, the string s1, which has a value of "MyTest", is already interned because it is a literal in the program. The System.Text.StringBuilder class generates a new string object that has the same value as s1. A reference to that string is assigned to s2. The Intern method searches for a string that has the same value as s2. Because such a string exists, the method returns the same reference that is assigned to s1. That reference is then assigned to s3. References s1 and s2 compare unequal because they refer to different objects; references s1 and s3 compare equal because they refer to the same string.
string s1 = "MyTest"; string s2 = new StringBuilder().Append("My").Append("Test").ToString(); string s3 = String.Intern(s2); Console.WriteLine((Object)s2==(Object)s1); //Different references. Console.WriteLine((Object)s3==(Object)s1); //The same reference.
要注意的关键是,对于 CLR,string.Format("Hello{0}", 5)
生成的字符串不会被视为文字字符串,因此当程序集已加载。另一方面,字符串 "hello"
由 CLR 驻留。为了实习这些字符串,您必须使用 String.Intern 明确地这样做。
编辑
关于您的锁定问题,理论上您可以使用字符串作为锁定对象,但我认为这是不好的做法。您不知道传递给应用程序的字符串来自何处,因此不能保证它们是相同的引用。这些字符串可能来自数据库读取调用、使用 StringBuilder、使用 String.Format 或用户输入。在这些情况下,您的锁定不能确保一次只有一个线程在您的临界区中,因为不能保证会发生字符串实习。
即使您可以保证您始终使用内部字符串,您仍然会遇到潜在的危险问题。现在任何人都可以在您的应用程序(包括其他 AppDomain)中的任何地方锁定相同的字符串引用。这是个坏消息。
我建议有一个显式声明的锁对象(对象类型)。如果出现线程问题,您将节省大量时间来调试线程问题。
关于c# - CLR 字符串引用不(总是)匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12829679/