编组.NETgenerics类型

这是一个C#程序,它在几种不同的类型上尝试Marshal.SizeOf

 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()); } } 

对M()的前四次调用成功,但在最后一次调用时,SizeOf会抛出ArgumentException:

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

为什么? 具体来说,为什么SizeOf会阻塞C ,而不是BC


编辑:因为在评论中被问及,这是“现实世界”的问题,这启发了这个主要是学术性的问题:我正在调用一个C API,它基本上是一个C函数,可以操作(指向)很多不同类型的简单C结构。 所有包含一个公共标题后跟一个字段,但该字段的类型在不同的结构中是不同的。 标题中的标志表示字段的类型。 (奇怪,是的,但这就是我必须要合作的东西)。

如果我可以定义一个generics类型C和一个C#extern声明M(C) ,然后在一行上调用M(C)在另一行上调用M(C) ,我有一个简短而甜蜜的互操作解决方案。 但是考虑到JaredPar的回答,似乎我必须为每个结构创建一个单独的C#类型(尽管inheritance可以提供公共头)。

任何互操作方案都不支持generics作为规则。 如果您尝试编组generics类型或值,则P / Invoke和COM Interop都将失败。 因此,我认为Marshal.SizeOf在这种情况下是未经测试或不受支持的,因为它是一个特定于元帅的函数。

不知道聚合对象T将具有什么大小(如果T是参考类型,则它将是指针的大小,如果是值类型,则大多数是任何值)。

我认为你可以通过在字段’value’上设置MarshalAs属性来指定最匹配的类型(例如,Unmanagedtype.SysInt)来解决这个问题。 请注意,它仍然不适用于所谓的不可映射类型(即无法轻易推断出字段偏移和大小的类型)。

但是AFAIK,不建议在互操作中使用generics。