2010-08-01 57 views
10

由於我不確切知道觸發錯誤的部分,我不完全確定如何更好地標記它。可能的C#4.0編譯器錯誤,可以通過別人驗證嗎?

此問題是SO問題c# code seems to get optimized in an invalid way such that an object value becomes null的副產品,我試圖幫助Gary與昨天晚上。他是發現問題的人,我剛剛將問題簡化爲一個更簡單的項目,並且在繼續深入之前需要驗證,因此在此提出這個問題。

我會在微軟發佈連接的說明,如果其他人可以驗證他們也搞定這個問題,當然,我希望無論是喬恩的Mads或埃裏克將在它的外觀以及:)

它包括:

  • 3個項目,其中2個是類庫,其中之一是一個控制檯程序(不需要這最後一個重現該問題,但只是執行這個說明什麼問題,而你需要使用反射器,並查看編譯的代碼,如果你不添加它)
  • 不完整的引用和類型推斷ENCE
  • 泛型

的代碼可以在這裏找到:code repository

如果您想讓自己的手變髒,我將在下面發佈如何製作項目的說明。

在返回一個簡單的通用列表之前,通過在方法調用中產生一個無效的強制類型,在返回它之前將其強制轉換爲奇怪的東西,從而表現出自身的問題。原始代碼最終以一個布爾值轉換爲布爾值,是的,一個布爾值。在返回結果之前,編譯器將List<SomeEntityObject>中的一個強制轉換爲布爾值,方法簽名表示它將返回List<SomeEntityObject>。這反過來會導致運行時出現奇怪的問題,從方法調用的結果被認爲是「優化掉」(原始問題),或者與BadImageFormatExceptionInvalidProgramException或其中一個類似的例外發生崩潰。

在我的工作重現此過程中,我看到一個演員陣容爲void[],而我現在的代碼版本現在轉換爲TypedReference。在這種情況下,Reflector會崩潰,所以在這種情況下,代碼很可能超出希望。你的里程可能有所不同

這裏是做什麼重現它:

注:有可能有一些會重現該問題更最小的形式,而是將所有的代碼只有一個項目使其消失。從類中刪除泛型也會導致問題消失。下面的代碼重現了我每次都遇到的問題,所以我將它保持原樣。

我在下面的代碼轉義HTML字符道歉,這是降價打了我一招,如果有人知道我怎麼能糾正它,請讓我知道,或者只是編輯的問題

  1. 爲.NET 4.0創建包含控制檯應用程序的新Visual Studio 2010解決方案
  2. 添加兩個新項目,這兩個類庫也是.NET 4。0(我將承擔他們命名爲ClassLibrary1的和ClassLibrary2)
  3. 調整所有的項目中使用完整的.NET 4.0運行時,不只是客戶端配置文件
  4. 在控制檯項目添加引用ClassLibrary2
  5. 在ClassLibrary2添加引用ClassLibrary 1
  6. 刪除被默認添加到類庫兩個文件的Class1.cs
  7. 在ClassLibrary1的,添加引用System.Runtime.Caching
  8. 添加將新文件添加到ClassLibrary1,將其稱爲DummyCache.cs,然後粘貼i n個以下代碼:

    using System; 
    using System.Collections.Generic; 
    using System.Runtime.Caching; 
    
    namespace ClassLibrary1 
    { 
        public class DummyCache<TModel> where TModel : new() 
        { 
         public void TriggerMethod<T>() 
         { 
         } 
         // Try commenting this out, note that it is never called! 
         public void TriggerMethod<T>(T value, CacheItemPolicy policy) 
         { 
         } 
         public CacheItemPolicy GetDefaultCacheItemPolicy() 
         { 
          return null; 
         } 
         public CacheItemPolicy GetDefaultCacheItemPolicy(IEnumerable<string> dependentKeys, bool createInsertDependency = false) 
         { 
          return null; 
         } 
        } 
    } 
    
  9. 添加新文件ClassLibrary2,稱之爲Dummy.cs並粘貼在下面的代碼:

    using System; 
    using System.Collections.Generic; 
    using ClassLibrary1; 
    
    namespace ClassLibrary2 
    { 
        public class Dummy 
        { 
         private DummyCache<Dummy> Cache { get; set; } 
         public void TryCommentingMeOut() 
         { 
          Cache.TriggerMethod<Dummy>(); 
         } 
         public List<Dummy> GetDummies() 
         { 
          var policy = Cache.GetDefaultCacheItemPolicy(); 
          return new List<Dummy>(); 
         } 
        } 
    } 
    
  10. 在Program.cs中下面的代碼粘貼在控制檯項目:

    using System; 
    using System.Collections.Generic; 
    using ClassLibrary2; 
    
    namespace ConsoleApplication23 
    { 
        class Program 
        { 
         static void Main(string[] args) 
         { 
          Dummy dummy = new Dummy(); 
          // This will crash with InvalidProgramException 
          // or BadImageFormatException, or a similar exception 
          List<Dummy> dummies = dummy.GetDummies(); 
         } 
        } 
    } 
    
  11. 構建,並確保沒有編譯器錯誤

  12. 現在嘗試運行該程序。這可能會導致一個更可怕的例外。我已經看到InvalidProgramException和BadImageFormatException,這取決於演員最後結果如何
  13. 查看Reflector中Dummy.GetDummies的生成代碼。源代碼如下所示:

    public List<Dummy> GetDummies() 
    { 
        var policy = Cache.GetDefaultCacheItemPolicy(); 
        return new List<Dummy>(); 
    } 
    

    然而反射說(對我來說,它可能會有所不同,其中投它選擇了你,在一種情況下反射甚至崩潰):

    public List<Dummy> GetDummies() 
    { 
        List<Dummy> policy = (List<Dummy>)this.Cache.GetDefaultCacheItemPolicy(); 
        TypedReference CS$1$0000 = (TypedReference) new List<Dummy>(); 
        return (List<Dummy>) CS$1$0000; 
    } 
    

現在,這裏的一對夫婦的奇怪的事情,上面的崩潰/無效代碼旁白:

  • Library2,其中有Dummy.GetDummies,執行調用以從Library1獲取該類的默認緩存策略。它使用類型推斷var policy = ...,結果是一個CacheItemPolicy對象(代碼中爲null,但類型很重要)。

    但是,ClassLibrary2沒有對System.Runtime.Caching的引用,所以它不應該編譯。

    事實上,如果你註釋掉虛擬方法名爲TryCommentingMeOut,您可以:

    類型「System.Runtime.Caching.CacheItemPolicy」在未引用的程序集定義。您必須添加對程序集「System.Runtime.Caching,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a」的引用。

    爲什麼使用這種方法讓編譯器感到高興我不知道,我甚至不知道這是否與當前問題有關。也許這是第二個錯誤。

  • 有在DummyCache類似的方法,如果您還原方法Dummy,使代碼再編譯,然後在DummyCache註釋掉的方法已經「嘗試評論了這一點,」它上面的評論,你得到相同的編譯器錯誤

+0

降價問題就在這裏:http://meta.stackexchange.com/questions/19624/markdown-formatting-錯誤與代碼塊在列表/ 19799#19799底線,我真的會避免把代碼內的編號列表,除非你絕對積極*有*。 – 2010-08-01 22:06:28

+0

當我運行此代碼時(BadImageFormatException),我得到同樣的問題。 – 2010-08-01 22:42:15

+0

發佈到Microsoft Connect:https://connect.microsoft.com/VisualStudio/feedback/details/585116/possible-compiler-error-in-c-4-0-related-to-generics-missing-project-references-和類型推理 – 2010-08-10 13:43:34

回答

2

好的,我下載了你的代碼,並可以按照描述確認問題。

我還沒有對此做過任何廣泛的修補,但是當我運行&反射器時,發佈版本似乎都可以(=空參考異常和乾淨的反彙編)。
Reflector(6.10.11)在Debug版本上崩潰。

另一個實驗:我想知道如何使用CacheItemPolicies,以便用我自己的MyCacheItemPolicy(在第三個classlib中)替換它,並彈出相同的BadImageFormat異常。

異常提到:{ 「壞二進制簽名(從HRESULT異常:0x80131192)」}

+0

是的,我應該提到我不相信有任何關於「CacheItemPolicy」引入了這個問題,它只是第一個類庫知道第二類不知道的任何類。 – 2010-08-01 19:02:50

+0

雖然,發佈版本仍不能正確處理缺失的引用,但如果我離開「TryCommentingMeOut」方法,它仍然有點困惑。 – 2010-08-01 19:07:08

+0

你能定義'有點困惑'嗎?我繼續使用MyCacheItemPolicy,如果我填充緩存屬性,它將運行W/O異常。你是否故意留下財產?我可以使用ClassLib2中的Optimize複選框打開/關閉該問題。 – 2010-08-01 19:32:29

相關問題