2010-01-14 97 views
10

一些特殊的CLI類型從mscorlib程序庫(ArgIteratorTypedReferenceRuntimeArgumentHandle類型)不能被用作一般類型參數構造通用類型/方法:C#類型參數規範

void Foo<T>() { } 
void Bar() { Foo<ArgIterator>(); } 

提供編譯器錯誤:

error CS0306: The type 'System.ArgIterator' may not be used as a type argument 

但是這在C#規範中完全沒有記錄。

這是類型是CLI說明書的一部分或該類型由CLR實現和上面描述不應在C#規範進行記錄的行爲提供?

+2

而且也是無效的,並不令人驚訝。 –

回答

10

首先,喬恩又是正確的 - 這些人是非常特殊類型其值無法轉換爲對象,所以不能用作類型參數。所有類型參數都必須是其值可轉換爲對象的類型。

要回答你的問題有關文檔:

的特殊功能,用於處理可變參數方法都不是記錄在案。他們不是C#語言本身的一部分 - 語言的一致性實現不需要能夠與支持可變參數方法的語言進行互操作。這些功能也不在MSDN中記錄爲編譯器文檔的一部分。這些不是「官方支持」的功能。

這是不幸的,但只有這麼多的預算可用,我想大多數人會同意我們會寫更好的功能和修復錯誤,而不是花錢記錄功能,99.99%的用戶永遠不會,即使他們得到支持也會使用,而他們不支持。

如果你想在C#中使用可變參數方法進行互操作,那麼你就是自己的。祝你好運!

+0

我錯了,認爲這個功能是「官方」的。謝謝你,埃裏克! :) – ControlFlow

6

我相信這是因爲這些類型的「特殊」,因爲它們不能被轉換爲object;只能將可以轉換爲object的類型指定爲類型參數。順便說一下,指針也是如此。

我找不到在哪裏,這是記錄(它的記錄爲指針在4.4.1),但埃裏克利珀在評論前些天提到它。

這只是一個利益的問題,或者你是否試圖實際上東西使用這種東西?

+1

當然這只是一個有趣的綜合例子,我用mscorlib中的所有valuetypes測試了一些泛型代碼,並創建了這個問題,但在C#規範中沒有找到任何解釋......我明白,這種類型非常特殊,ArgIterator是實際上是一個大小不同的結構......但沒有解釋! :) – ControlFlow

1

所有這三個,你所提供的例子是結構,而不是類,所以我懷疑這就是問題的關鍵。關於compiler error message的文檔中提供的示例還指出,如果在泛型中使用指向類型的指針,則會失敗。

+0

結構是允許的,ArgIterator,一個,不包含指針。我已經嘗試過一個包含IntPtr字段的自定義結構,並且工作正常。努力查看是什麼導致了錯誤。也許它涉及到外部或不安全的方法。 –

1

第8.2節。CLI spec中的4個調用的值類型可以包含指向評估堆棧「byref-like」類型的指針,並表示它們不能被裝箱。它明確提出了System.RuntimeArgumentHandleSystem.TypedReference作爲這種類型的例子,但沒有提供詳盡的清單。 9.4節繼續指出byref類型,byref類型,並且System.Void不能用於實例化泛型類型或方法。

1

就像一條評論,當試圖編譯不能轉換爲對象的類型的代碼時,可以使用更多的樂趣。當您輸入.(點)時,這裏的所有方法都會被Visual Studio建議。

ArgIterator.ReferenceEquals(new object(), new object()); // OK; static method inherited from System.Object 

    var strange = default(ArgIterator); 
    strange.End();   // OK; non-virtual method defined in the struct 
    strange.GetHashCode(); // OK; method overridden in the struct 
    strange.ToString();  // compile-time error; method overriden in System.ValueType, inherited but not overridden in the struct 
    strange.GetType();  // compile-time error; non-virtual method inherited from System.Object