Subscribed unsubscribe Subscribe Subscribe

P/Invoke (Platform Invoke) などマーシャル属性を持つクラスにはジェネリック型を関連づけられない

.NET C# generics PInvoke

これにも昨日からずっとハマってました。次のようなコードで再現します。

using System;
using System.Runtime.InteropServices;

public class Bar<T>
{
	[DllImport("kernel32.dll")]
	public static extern void Beep(UInt32 freq, UInt32 duration);
}

public class Foo
{
	static void Main(string[] args)
	{
		new Bar<int>();
	}
}

これ、コンパイルはできるのですが、実行してみると次のようなランタイムエラーとなります。

ハンドルされていない例外: System.TypeLoadException: ジェネリック メソッドまたはジェネリック クラスのメソッドは内部呼び出し、PInvoke であるか、または COM インポート クラスで定義されています。
   場所 Foo.Main(String[] args)

目下これを防ぐには、一旦ジェネリックでない版のクラスを作りそこでマーシャルするようにして、ジェネリック版はその非ジェネリック版を継承する形で作るという道しかないようです。

これが許されていない理由はなんとなく察しはつくのですが (実行時にジェネリッククラス名と関連づけてスタブを自動生成するため)、それにしてもちょっと不便だ。