2013-03-24 164 views
4
展示NoStringInterning

CompilationRelaxations.NoStringInterning如何实际工作?

[assembly: System.Runtime.CompilerServices.CompilationRelaxations(System.Runtime.CompilerServices.CompilationRelaxations.NoStringInterning)] 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      String s1 = "Friday"; 
      String s2 = "Friday"; 
      String s3 = "Friday"; 
      String s4 = "Friday"; 
      String s5 = "Friday"; 
      String s6 = "Friday"; 
      String s7 = "Friday"; 
      String s8 = "Friday"; 
      String s9 = "Friday"; 
      // etc... 
      Console.WriteLine(Object.ReferenceEquals(s1, s2)); 
      Console.WriteLine(Object.ReferenceEquals(s1, s3)); 
      Console.WriteLine(Object.ReferenceEquals(s1, s4)); 
      Console.WriteLine(Object.ReferenceEquals(s1, s5)); 
      Console.WriteLine(Object.ReferenceEquals(s1, s6)); 
      Console.WriteLine(Object.ReferenceEquals(s1, s7)); 
      Console.WriteLine(Object.ReferenceEquals(s1, s8)); 
      Console.WriteLine(Object.ReferenceEquals(s1, s9)); 
      // etc... 

我有问题,我试着用.NET CLR 2,3,4 ..作为输出我得到的是一堆真。我期待着一大堆假!

回答

5

documentation状态,属性:

标记的组件为不需要字串文本实习。

换句话说,它不会阻止编译器进行字符串实习,只是提供一个不需要的提示。这方面的文件有点稀疏,但这似乎也是this MSDN forum post的结论。

+0

驱动程序,如果我在编译后查看IL DASM,我会看到一堆带有ldstr“Friday”的行。你写“不妨碍编译器进行字符串实习”这与编译器有什么关系?如果编译器正在进行实习,那么该方法中不应只有一个“周五”?为什么我不得不付出加载这个常数一堆的价格,并让运行时间来清理重复项?我很困惑... – Mishax 2013-03-24 20:58:24

+0

我不认为ILDASM给你这里的完整故事。这个字符串可能只在#US堆中存在一次,并且CLR在#US堆中每个字符串实例化一个字符串对象(而不是每个唯一字符序列中的一个,而普通字符串实际存在)。由于ILDASM将#US堆引用替换为实际的字符串文字,我认为您需要使用一些较低级别的工具来查看实际存在的内容。 – poizan42 2015-07-23 14:56:45

0

的MSDN描述为NoStringInterning说

“标记的组件为不需要字串文本实习”。

说一个程序集不需要实习并不是说应该关闭这个功能。 AFAIK没有办法做到这一点(NGEN除外)。

5

没有打开一扇门,但显然这个属性并没有做到你认为的那样。在MSDN和CLI规范中,它的文档都很差。从CLR中的使用来看,唯一明显的是,当它打开时,编译器只需确保相同的字符串在模块级别被执行。这有许多副作用,这些副作用与内联,自由和混合模式程序集有关。

这会迫使我解释模块和组件之间的确切区别。我不能这样做,模块是一些奇怪的怪物,它们在.NET编程中没有实际的用处。最好忘记这个属性是相关的。除非你有一个使用/ target:module选项运行C#编译器的自定义编译系统,否则C#编译器总是在汇编级实习,所以你的测试总是会产生“true”。