Marshalling tipos generics .NET

Aquí hay un progtwig de C # que intenta Marshal.SizeOf en algunos tipos diferentes:

 using System; using System.Runtime.InteropServices; [StructLayout(LayoutKind.Sequential)] class AClass { } [StructLayout(LayoutKind.Sequential)] struct AStruct { } [StructLayout(LayoutKind.Sequential)] class B { AClass value; } [StructLayout(LayoutKind.Sequential)] class C { T value; } class Program { static void M(object o) { Console.WriteLine(Marshal.SizeOf(o)); } static void Main() { M(new AClass()); M(new AStruct()); M(new B()); M(new C()); M(new C()); } } 

Las primeras cuatro llamadas a M () tienen éxito, pero en la última, SizeOf lanza una ArgumentException:

 "Type 'C`1[AClass]' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed." 

¿Por qué? Específicamente, ¿por qué SizeOf se ahoga en C , pero no en B o en C ?


EDITAR: Debido a que se le preguntó en los comentarios, aquí está el problema del “mundo real” que inspiró esta pregunta principalmente académica: estoy llamando a una API de C que es básicamente una función de C que opera (apunta a) un montón de Diferentes tipos de estructuras en C simples. Todos contienen un encabezado común seguido de un campo, pero el tipo de ese campo es diferente en diferentes estructuras. Una bandera en el encabezado indica el tipo de campo. (Extraño, sí, pero eso es con lo que tengo que trabajar).

Si pudiera definir un solo tipo genérico C y una única statement externa de C # M(C) , y luego llamar a M(C) en una línea, y M(C) en otra , Tendría una solución de interoperabilidad corta y dulce. Pero dada la respuesta de JaredPar, parece que tengo que hacer un tipo C # separado para cada estructura (aunque la herencia puede proporcionar el encabezado común).

Los generics como regla no se admiten en ningún escenario de interoperabilidad. Tanto P / Invoke como COM Interop fallarán si intenta calcular un tipo o valor genérico. Por lo tanto, esperaría que Marshal.SizeOf no esté probado o no sea compatible para este escenario, ya que es una función específica del gerente.

No se sabe qué tamaño tendría el objeto agregado T (sería el tamaño de un puntero si T es un tipo de referencia y, en su mayoría, cualquier valor si es un tipo de valor).

Creo que puede resolver este problema configurando el atributo MarshalAs en el campo ‘valor’ que especifica el tipo más coincidente (por ejemplo, Unmanagedtype.SysInt). Tenga en cuenta que todavía no funcionará para los llamados tipos no asignables (es decir, los tipos para los cuales no se pueden deducir fácilmente los desplazamientos y tamaños de campos).

Pero AFAIK, no se recomienda usar generics en la interoperabilidad.