2010-01-14 13 views
10

Algunos tipos especiales de la CLI desde mscorlib biblioteca (ArgIterator, TypedReference y RuntimeArgumentHandle tipos) no se pueden utilizar como parámetros de tipo genérico para construir los genéricos tipos/métodos:C parámetros # tipo de especificación

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

proporciona el error del compilador :

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

Pero esto no está documentado en absoluto en la especificación C#.

¿Estos tipos son parte de la especificación CLI o estos tipos proporcionados por la implementación CLR y el comportamiento descrito anteriormente no deberían documentarse en la especificación C#?

+2

Y vacío también, no tan sorprendentemente. –

Respuesta

10

En primer lugar, Jon es más correcto - estos tipos son tipos muy especiales cuyos valores no son convertibles a oponerse, por lo que no puede ser utilizado como argumentos de tipo. Todos los argumentos de tipo deben ser tipos cuyos valores sean convertibles a objeto.

Para responder a su pregunta acerca de la documentación:

Ninguna de las características especiales para el manejo de métodos variadic están documentados. No son parte del lenguaje C# en sí: no se requiere una implementación conforme del lenguaje para poder hacer interoperabilidad con los lenguajes que admiten los métodos variadic. Tampoco se documentan estas características en MSDN como parte de la documentación del compilador. Estas no son características "oficialmente compatibles".

Esto es desafortunado, pero hay mucho presupuesto disponible, y creo que la mayoría de la gente estaría de acuerdo en que sería mejor escribir características y corregir errores que gastar dinero documentando características que literalmente el 99.99% de nuestros usuarios nunca , alguna vez usar incluso si fueron compatibles, que no lo son.

Si quieres hacer interoperabilidad en C# con varios métodos, estás solo. ¡Buena suerte!

+0

Me equivoqué al pensar que estas características son "oficiales". Gracias, Eric! :) – ControlFlow

6

Creo que es porque estos tipos son "especiales" en el sentido de que no se pueden convertir a object; solo los tipos que se pueden convertir a object se pueden especificar como argumentos de tipo. Lo mismo es cierto para los indicadores, por cierto.

No puedo encontrar el lugar donde está documentado (está documentado para los punteros en 4.4.1) pero Eric Lippert lo mencionó en un comentario el otro día.

¿Es esto solo una cuestión de interés, o está tratando de realmente hacer algo con este tipo de cosas?

+1

Por supuesto, esto es solo un ejemplo de interés y sintético, estaba probando un código genérico con todos los tipos de valor de mscorlib y fundado este problema, pero no encontré explicación en la especificación C# ... Entiendo que este tipo es muy especial, ArgIterator es en realidad una estructura con tamaño variable ... ¡pero sin explicación! :) – ControlFlow

1

Los tres ejemplos que proporcionó son estructuras, y no clases, así que sospecho que esa es la clave del problema. Un ejemplo proporcionado en la documentación en el compiler error message indica también que si utiliza un puntero a un tipo en el genérico, fallaría.

+0

Las estructuras están permitidas y el ArgIterator, por ejemplo, no contiene punteros. He intentado una estructura personalizada que contenga campos IntPtr y esto funciona bien. Luchando para ver qué está causando el error. Quizás esté relacionado con los métodos externos o inseguros. –

1

Sección 8.2.4 de CLI spec llama a tipos de valor que pueden contener punteros en la pila de evaluación tipo "byref" y dice que no se pueden encasillar. Llama explícitamente a System.RuntimeArgumentHandle y System.TypedReference como ejemplos de dichos tipos, pero no proporciona una lista exhaustiva. La Sección 9.4 continúa para indicar que los tipos byref, los tipos tiporef y System.Void no se pueden usar para crear instancias de tipos o métodos genéricos.

1

Al igual que un comentario, aquí hay algo más de diversión que puede tener al intentar compilar código con este tipo que no es convertible a objeto. Todos los métodos aquí aparecen como sugerencias de Visual Studio cuando escribe . (punto).

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 
Cuestiones relacionadas