Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9691

C# ジェネリック(ジェネリクス)の実践使用例

$
0
0

前置き

当記事は、前回の「C# ジェネリック(ジェネリクス)」の続編です。
ジェネリックを活用できそうな関数を紹介します。

概要

使用する関数は、WinAPIのひとつである「ReadProcessMemory()」です。
これは、特定のアドレスにあるメモリを読み取ります。
具体的には、以下の通りです。

[DllImport("kernel32.dll")]publicstaticexternintReadProcessMemory(IntPtrhProcess,IntPtrBaseAddress,byte[]Buffer,intsize,intBytesRead);

読み取られた値は引数のbufferbyteとして格納されます。
ここで、読み取られた値はアンマネージド型のいずれかであることが保証されます。
例えば、Int32(int)を読み取りたい時、

BitConverter.ToInt32(buffer,0);

といちいち型別に関数を定義するのは面倒ですし、プログラムの保守性やメンテナンス性も最悪です。
読み取り先の値はintfloatdouble等のアンマネージド型ですね。
そうです。ジェネリックの出番です。

ジェネリック関数としてWrap

早速、関数をWrapしてみます。
理想は以下の様に簡単にすることです。

IntPtraddress=...intx=Read<int>(address);

ソースコード:

publicstaticunsafeTRead<T>(IntPtrhProc,IntPtraddress)whereT:unmanaged{varsize=sizeof(T);byte[]buffer=newbyte[size];ReadProcessMemory(hProc,address,buffer,buffer.Length,0);Span<T>span=MemoryMarshal.Cast<byte,T>(buffer);returnspan[0];}

解説:

制約はunmanagedです。
ここでは、読み取った値(byte[])をMemoryMarshal.Cast<TFrom, TTo>(byte[])を使用してキャストしています。
byte[]はマネージ型であるため、アンマネージド型へのキャストには少し工夫が必要です。
それを代行してくれるのが、MemoryMarshal.Castです。
そして、返り値はSpan<T>として帰ってきます。
Span<T> spanは配列であり、キャストした値を配列から取り出して返り値としています。

MSDN: 「Span 構造体」
MSDN: 「MemoryMarshal.Cast メソッド」


Viewing all articles
Browse latest Browse all 9691

Trending Articles