byte[] -> T*への道

ここのところずっとやっていたネタですが、実はこんな事しなくても良いことが判明して使い道が無くなってしまいました。(^^; ま、折角なので日記ネタとして継続します。
T*がコンパイル出来ないのはC#の制限なので、ILアセンブラで書いてしまうことに。

C#では書けないコード

public static unsafe T* Foo<T>(byte[] bytes)
{
      return (T*) Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0);
}

コイツをILで書くと

  .method public hidebysig static !!T* 
          Foo<T>(uint8[] bytes) cil managed
  {
    // コード サイズ       18 (0x12)
    .maxstack  2
    .locals init (!!T* V_0)
    IL_0000:  nop
    IL_0001:  ldarg.0
    IL_0002:  ldc.i4.0
    IL_0003:  call       native int [mscorlib]System.Runtime.InteropServices.
    Marshal::UnsafeAddrOfPinnedArrayElement(class [mscorlib]System.Array, int32)
    IL_0008:  call       void* [mscorlib]System.IntPtr::op_Explicit(native int)
    IL_000d:  stloc.0
    IL_000e:  br.s       IL_0010

    IL_0010:  ldloc.0
    IL_0011:  ret
  } // end of method App::Foo

こんな感じ。!!T*に注目です。

ちなみに呼び出しは、

    IL_0015:  call       !!0* App::Foo(uint8[])

generic型が!!Tではなく!!0になっているのに注意です。多分、0番目の型パラメータという意味だと思います。

結局、ILで書いてもメソッドのパラメータにT*があるとC#コンパイル出来ないし、Tに戻すと値型なのでコピーが発生してしまい、使えないということでボツとなりました。(^^;