雖然試圖創建在一個C/CLI包裝翻譯單元範圍的靜態對象爲本地C++ lib中,我跑成問題與使用auto關鍵字。 C++/CLI包裝器是純粹的功能,所以我需要使用ConcurrentDictionary在調用之間保持一些狀態(以處理託管< - >本地代理翻譯)。我第一次嘗試這個(簡化):
static ConcurrentDictionary<String^, String^>^ GlobalData1 = gcnew ConcurrentDictionary<String^, String^>();
但這失敗,編譯:
具有靜態存儲持續時間的變量不能具有手柄或跟蹤引用類型
對於簡單,我決定繼續使用類型扣除,同時我找到了問題:
static auto GlobalData3 = gcnew ConcurrentDictionary<String^, String^>();
令我驚訝的是,編譯和鏈接!我去寫更多的代碼一段時間,然後我跑我的,它使用C++/CLI包裝C#測試應用程序並獲得了未處理的運行時異常:
未處理的異常:System.IO.FileLoadException:無法加載文件或程序程序集'DotNetTestLibWrapper,Version = 1.0.6111.33189,Culture = neutral,PublicKeyToken = null'或其依賴項之一。無法找到或加載類型。 (來自HRESULT的異常:0x80131522)---> System.TypeLoadException:從程序集'DotNetTestLibWrapper,Version = 1.0.6111.33189,Culture = neutral,PublicKeyToken = null'中輸入''具有非法類型的字段。
我沒有馬上知道這個問題是什麼,因爲我做了其他編輯。通過打開融合日誌並使用Fuslogvw.exe,我終於獲得了更多信息。問題是類型推導出的靜態ConcurrentDictionary。
我創建了一個SSCCE證明問題:https://github.com/calebwherry/DotNetWrapperForNativeCppLibrary
在這篇文章中描述的位於此處的代碼:https://github.com/calebwherry/DotNetWrapperForNativeCppLibrary/blob/master/DotNetTestLibWrapper/DotNetTestLibWrapper.cpp
MSVS版本:
微軟的Visual Studio社區2015年版14.0。 25431.01更新3 Microsoft .NET Framework版本4.6.01038
問題
這些都導致編譯器錯誤:
static ConcurrentDictionary<String^, String^>^ GlobalData1 = gcnew ConcurrentDictionary<String^, String^>();
static auto^ GlobalData2 = gcnew ConcurrentDictionary<String^, String^>();
但這編譯+鏈接,但會導致非法類型的未處理的運行時異常:
static auto GlobalData3 = gcnew ConcurrentDictionary<String^, String^>();
這是怎麼回事,併爲什麼會發生? MSVS似乎認爲(閱讀:智能感知如此)auto
和auto^
定義是相同的。但是,它們顯然不是一個編譯而另一個不編譯。
注:閱讀一些有關原始編譯器的問題後,該問題的實際解決方案是這樣的:
ref struct GlobalData
{
static ConcurrentDictionary<String^, String^>^ GlobalData4 = gcnew ConcurrentDictionary<String^, String^>();
};
這很好,我只是好奇,什麼是真正發生的事情與該類型推演。
我不知道如果編譯器能夠支持管理「靜態」存儲通過定義這樣的編譯器生成的類*和*從模塊初始化調用它的靜態構造函數。 –
好吧,它不需要CLR支持靜態構造函數。而他們沒有。 –