スキップしてメイン コンテンツに移動

投稿

ラベル(struct)が付いた投稿を表示しています

C#のClassとStruct

C#のClassとStructの性能や使い分けについてメモ。 https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct https://medium.com/@mdfarragher/whats-faster-in-c-a-struct-or-a-class-99e4761a7b76 https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/choosing-between-class-and-struct?redirectedfrom=MSDN

C#でMarshalクラスを使ってbyte配列から構造体を生成する方法

C#の通信プログラムでbyte配列を読み込んで、構造体(struct)を生成したいときにサンプルコードの紹介です。 Genericsを使って任意の構造体をbyte配列から生成できるようにしています。 public static T ReadAsStruct < T > ( this byte [ ] bytes , int startIndex ) where T : struct { // GCHandle.Allocクラスを使ってメモリ上のデータがガーベッジコレクタの対象にならないようにする。 var handle = GCHandle . Alloc ( bytes , GCHandleType . Pinned ) ; try { // Marshalクラスのメソッドを使って、byte配列のIntPtr(ポインタ)を取得。 var ptr = Marshal . UnsafeAddrOfPinnedArrayElement ( bytes , startIndex ) ; // IntPtrで指定した位置のbyte配列から構造体を生成。 return ( T ) Marshal . PtrToStructure ( ptr , typeof ( T ) ) ; } finally { // 重要!!必ずGCHandleを開放して、再びbyte配列がガーベッジコレクタの対象になるようにする。 handle . Free ( ) ; } } ちょっと考察 ■ パフォーマンス 毎回GCHandle.Alloc, Freeを行う分、パフォーマンスのオーバーヘッドが発生します。パフォーマンスが気になる場合は、GCHandle.Alloc, Freeの間に、複数の構造体を生成するようにするとよいかもしれません。 ■ 他の書き方 startIndexがいつもゼロの場合、下記の部分は、 var ptr = Marshal . UnsafeAddrOfPinnedArrayElem