2013-03-24 111 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」。