2009-10-16 68 views
7

這裏是一個嘗試的幾個不同類型的Marshal.SizeOf C#程序:編組站.NET泛型類型

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> { 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<AStruct>()); 
     M(new C<AClass>()); 
    } 
} 

前四個調用M()成功,但在最後一個,一下SizeOf引發ArgumentException:

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

爲什麼?具體來說,爲什麼SizeOf窒息C<AClass>,而不是BC<AStruct>


編輯:因爲它在評論中問道一下,這裏的「現實世界」的問題,激發了大部分學術問題: 我打電話到一個C API,基本上是一種C函數在(指向)很多不同類型的簡單C結構上運行。全部包含一個共同的標題,後面跟着一個字段,但該字段的類型在不同的結構中是不同的。標題中的標誌指示字段的類型。 (奇怪,是的,但這是我必須合作的)。

如果我可以定義一個通用型C<T>和一個C#extern聲明M(C<T>),然後調用另一個M(C<int>)在一行,並M(C<double>),我有一個簡短而親切的互操作解決方案。但是根據JaredPar的回答,似乎我必須爲每個結構分別創建一個C#類型(儘管繼承可以提供通用頭文件)。

+0

拋出哪個異常? – 2009-10-16 18:14:40

+0

ArgumentException,與他粘貼的消息。 – 2009-10-16 18:16:49

+0

@Philipp:剛剛編輯澄清,謝謝。 – Gabriel 2009-10-16 18:17:45

回答

7

任何互操作方案都不支持泛型。如果您嘗試編組泛型類型或值,則P/Invoke和COM Interop都會失敗。因此,我認爲Marshal.SizeOf未被測試或不支持這種情況下,因爲它是一個元帥特定的功能。

0

不知道聚集對象T會有多大的大小(如果T是一個引用類型,它將是一個指針的大小,如果它是值類型,則大多數是任何值)。

我想你可以通過設置字段'值'指定最匹配的類型(例如,Unmanagedtype.SysInt)上的MarshalAs屬性來解決此問題。請注意,它對於所謂的不可映射類型(即無法輕鬆推導字段偏移和大小的類型)仍然不起作用。

但是AFAIK,不建議在interop中使用泛型。