C# 为什么两个单独的字符串引用相等?换句话说,为什么s和t都是相同的参考?
为什么两个字符串引用相同?我试图编写一个复制构造函数,希望避免指向同一字符串的字符串引用C# 为什么两个单独的字符串引用相等?换句话说,为什么s和t都是相同的参考?,c#,.net,.net-2.0,C#,.net,.net 2.0,为什么两个字符串引用相同?我试图编写一个复制构造函数,希望避免指向同一字符串的字符串引用 using System; namespace StringRefTest { class Program { public static void Main(string[] args) { Console.WriteLine("String Test!"); string s = "f"; // This
using System;
namespace StringRefTest
{
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("String Test!");
string s = "f"; // This should be one reference
string t = "f"; // This should be another
if (ReferenceEquals(s, t))
Console.WriteLine("Ref Same");
else
Console.WriteLine("Ref Not Same"); // Should be true
// The references are the same
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}
.引用是相等的,因为字符串文本得到。你所看到的是,s和t都被从那个弦乐实习生中拉了出来 更具启发性的是在以下两个方面调用
字符串。IsInterned
:
您应该看到这两个字符串实际上都是内部的,这意味着它们在内部指向相同的数据,因此具有相同的引用
我们之所以能够摆脱这种情况,唯一的原因是字符串在C#中是不可变的,正如您在其他答案提供的链接中所看到的那样。这是C#的字符串内部存储功能。发件人:
当一个程序声明两个或多个相同的字符串变量时,编译器会将它们全部存储在同一位置。与其他人所说的相反,这种行为不是由于字符串插入造成的。已编译程序集的元数据包含使用的字符串常量表。C#编译器足够聪明,可以注意到这两个字符串是相同的,并且对这两个字符串使用相同的常量。如果编译器没有注意到这一点,那么字符串的内部处理就是区别所在 为了证明这一点,我试着运行一个简单的程序,有实习和没有实习。根据CLR via C#,您可以在程序集上指定
[CompilationRelaxationsAttribute(CompilationRelaxations.NoStringInterning)]
属性,以建议关闭字符串内联。C#编译器总是发出此属性,但CLR v.4.0仅在使用ngen时才尊重此属性。这对我们来说很方便:
>interning.exe
s和t参考值相等:真
s被拘留了:是的
t被拘留了:是的
>ngen安装interning.exe
Microsoft(R)CLR本机映像生成器-版本4.0.30319.17020
版权所有(c)微软公司。版权所有。
1> 编译程序集C:\Users\Svick\AppData\Local\Temporary Projects\interni
ng\bin\Debug\interning.exe(CLR v4.0.30319)。。。
>interning.exe
s和t参考值相等:真
s被拘留:错
t被拘留:错
这证明了具有相同值的两个字符串常量引用相等时不需要字符串内部处理。@PaulRuane:字符串不可变的事实是高度相关的;字符串是不可变的这一事实让我们可以对其进行实习。虽然这篇文章对这个主题来说并不坏,但这篇文章实际上更直接地讨论了手头的主题:@Eric我知道它在你的博客上的某个地方,我找不到它,太多很棒的帖子。你能解释一下为什么你想避免那个非常令人向往的事情吗?字符串引用标识通常被认为是一个巨大的胜利,而不是可以避免的事情。你在做什么,你想避免它?其他海报是正确的。1) 这种行为是由字符串实习引起的。2)你很可能希望事情以这种方式进行。但是,如果您确定不希望出现这种行为,可以在程序集上使用此属性将其关闭:
[assembly:compilementrelaxations(compilementrelaxations.NoStringInterning)]
更多信息,请访问我想感谢这里的所有海报。我不太擅长理解C#中字符串管理的所有细微差别。谢谢你的解释。还有@Eric只要它一直有效你是对的,我就不想避免这个非常令人向往的事情!你确定在这种特殊情况下它会实习吗?我可以想象编译器只是合并了两个常量。@HenkHolterman,我认为你是对的,这个答案是错的。看看我的答案。
string s = "f";
string t = "f";
Console.WriteLine("Is Interned: {0}", String.IsInterned(s));
Console.WriteLine("Is Interned: {0}", String.IsInterned(t));