views:

339

answers:

4

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?

+5  A: 

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?

Jon Skeet
Of course this is only interest and synthetic example, I was testing some generic code with all the valuetypes from mscorlib and founded this issue, but found no explanation in C# spec... I understand, that this types are very special, ArgIterator is actually a struct with vary size... but no explanation! :)
ControlFlow
+1  A: 

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.

scwagner
Structs are allowed and the ArgIterator, for one, contains no pointers. I have tried a custom struct containing IntPtr fields and this works fine. Struggling to see what is causing the error. Perhaps it is related to the extern or unsafe methods.
Paul Ruane
+7  A: 

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!

Eric Lippert
I was wrong thinking this features are "official". Thank you, Eric! :)
ControlFlow
+1  A: 

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.

kvb