由於我不確切知道觸發錯誤的部分,我不完全確定如何更好地標記它。可能的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>
。這反過來會導致運行時出現奇怪的問題,從方法調用的結果被認爲是「優化掉」(原始問題),或者與BadImageFormatException
或InvalidProgramException
或其中一個類似的例外發生崩潰。
在我的工作重現此過程中,我看到一個演員陣容爲void[]
,而我現在的代碼版本現在轉換爲TypedReference
。在這種情況下,Reflector會崩潰,所以在這種情況下,代碼很可能超出希望。你的里程可能有所不同
這裏是做什麼重現它:
注:有可能有一些會重現該問題更最小的形式,而是將所有的代碼只有一個項目使其消失。從類中刪除泛型也會導致問題消失。下面的代碼重現了我每次都遇到的問題,所以我將它保持原樣。
我在下面的代碼轉義HTML字符道歉,這是降價打了我一招,如果有人知道我怎麼能糾正它,請讓我知道,或者只是編輯的問題
- 爲.NET 4.0創建包含控制檯應用程序的新Visual Studio 2010解決方案
- 添加兩個新項目,這兩個類庫也是.NET 4。0(我將承擔他們命名爲ClassLibrary1的和ClassLibrary2)
- 調整所有的項目中使用完整的.NET 4.0運行時,不只是客戶端配置文件
- 在控制檯項目添加引用ClassLibrary2
- 在ClassLibrary2添加引用ClassLibrary 1
- 刪除被默認添加到類庫兩個文件的Class1.cs
- 在ClassLibrary1的,添加引用System.Runtime.Caching
添加將新文件添加到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; } } }
添加新文件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>(); } } }
在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(); } } }
構建,並確保沒有編譯器錯誤
- 現在嘗試運行該程序。這可能會導致一個更可怕的例外。我已經看到InvalidProgramException和BadImageFormatException,這取決於演員最後結果如何
查看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
註釋掉的方法已經「嘗試評論了這一點,」它上面的評論,你得到相同的編譯器錯誤
降價問題就在這裏:http://meta.stackexchange.com/questions/19624/markdown-formatting-錯誤與代碼塊在列表/ 19799#19799底線,我真的會避免把代碼內的編號列表,除非你絕對積極*有*。 – 2010-08-01 22:06:28
當我運行此代碼時(BadImageFormatException),我得到同樣的問題。 – 2010-08-01 22:42:15
發佈到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