来自 mscorlib 库(ArgIterator
,TypedReference
和RuntimeArgumentHandle
类型)的一些特殊CLI类型不能用作泛型类型参数来构造泛型类型/方法:
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#规范中?
答案 0 :(得分:10)
首先,Jon再次正确 - 这些人是非常特殊的类型,其值不能转换为对象,因此不能用作类型参数。所有类型参数必须是其值可转换为对象的类型。
回答有关文档的问题:
没有记录处理可变方法的特殊功能。它们不是C#语言本身的一部分 - 语言的一致性实现不需要能够与支持可变方法的语言互操作。 MSDN中也没有将这些功能记录为编译器文档的一部分。这些不是“官方支持”功能。
这很不幸,但是只有这么多的预算可用,而且我认为大多数人都会同意我们更好地编写功能和修复错误,而不是花钱记录99.99%的用户永远不会的功能,即使他们得到支持也会使用,但他们不支持。
如果您想使用可变方法在C#中进行互操作,那么您就可以自己动手了。祝你好运!
答案 1 :(得分:6)
我相信这是因为这些类型“特殊”,因为它们无法转换为object
;只有可以转换为object
的类型才能被指定为类型参数。顺便说一句,指针也是如此。
我无法找到记录的位置(4.4.1中的指针已记录)但Eric Lippert前几天在评论中提到了它。
这只是一个有趣的问题,还是你想用这种东西做某事?
答案 2 :(得分:1)
您提供的所有三个示例都是结构,而不是类,所以我怀疑这是问题的关键。 compiler error message文档中提供的示例还表明,如果使用指向泛型中的类型的指针,则会失败。
答案 3 :(得分:1)
CLI spec的第8.2.4节调用值类型,它们可以包含指向评估堆栈“byref-like”类型的指针,并表示它们不能被装箱。它明确地将System.RuntimeArgumentHandle
和System.TypedReference
作为此类类型的示例,但未提供详尽的列表。第9.4节继续说明byref类型,byref类型和System.Void不能用于实例化泛型类型或方法。
答案 4 :(得分: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