Question

Some special CLI types from mscorlib library (ArgIterator, TypedReference and RuntimeArgumentHandle types) cannot be used as generic type parameters to construct the generic types / methods:

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

provides the compiler error:

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

But this is not documented at all in the C# specification.

Is this types are a part of CLI specification or this types provided by CLR implementation and the behavior described above should not be documented at C# spec?

Was it helpful?

Solution

First off, Jon is again correct -- these guys are very special types whose values are not convertible to object, and so cannot be used as type arguments. All type arguments must be types whose values are convertible to object.

To answer your question about documentation:

None of the special features for handling variadic methods are documented. They are not a part of the C# language itself -- a conforming implementation of the language is not required to be able to do interop with languages that support variadic methods. Nor are these features documented in MSDN as part of the compiler documentation. These are not "officially supported" features.

This is unfortunate, but there's only so much budget available, and I think most people would agree that we'd do better to write features and fix bugs than to spend money documenting features that literally 99.99% of our users will never, ever use even if they were supported, which they're not.

If you want to go do interop in C# with variadic methods, you're on your own. Good luck!

OTHER TIPS

I believe it's because these types are "special" in that they can't be converted to object; only types which can be converted to object can be specified as type arguments. The same is true for pointers, by the way.

I can't find where this is documented (it's documented for pointers in 4.4.1) but Eric Lippert mentioned it in a comment the other day.

Is this just a matter of interest, or are you trying to actually do something using this kind of thing?

All three of the examples that you provided are structs, and not classes, so I suspect that's the key to the problem. An example provided in the documentation on the compiler error message indicates also that if you use a pointer to a type in the generic it would fail.

Section 8.2.4 of the CLI spec calls value types which can contain pointers into the evaluation stack "byref-like" types and says that they cannot be boxed. It explicitly calls out System.RuntimeArgumentHandle and System.TypedReference as examples of such types but does not provide an exhaustive list. Section 9.4 goes on to state that byref types, byref-like types, and System.Void cannot be used to instantiate generic types or methods.

Just as a comment, here's some more fun you can have when trying to compile code with this type which is not convertible to object. All of the methods here come up as suggestions by Visual Studio when you type the . (dot).

  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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top