C#类型参数规范

时间:2010-01-14 13:58:26

标签: c# generics specifications type-parameter

来自 mscorlib 库(ArgIteratorTypedReferenceRuntimeArgumentHandle类型)的一些特殊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#规范中?

5 个答案:

答案 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.RuntimeArgumentHandleSystem.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