C#のコレクションと構造に関する注意。 メモリの問題

この情報は、実際に本を最後まで読まずに理論を理解しようとするC#に精通している人に役立ちます。 これはほとんどの場合、トピックの詳細な説明や分析ではなく、メモです。 C#でコレクションを操作するときのメモリ構造の動作に興味がある人はいらっしゃいません。



夕方にリヒターを読んだ後、私はそれぞれの詳細をより詳細に理解することに決めました。 本のページをスクロールすると、毎日設計され、書かれているものの多くが、.Netの基盤の一部に常に違反しているという結論に達しました。



構造とコレクションの例を考えてみましょう。 構造は値型であり、参照構造とは異なる動作をすることを思い出しません。



例1.古いArrayListを使用します。



System.Int32 myInt = 7; ArrayList al = new ArrayList(); al.Add(myInt);
      
      





期待される結果は、System.Int32型のスタックに2つの異なる要素が存在することです。 さらに、そのうちの1つは既に参照型になります。 このコードのIL表現を開くと、公正な確認が表示されます。



 IL_0002:stloc.0 // myInt
  IL_0003:newobj System.Collections.ArrayList..ctor
  IL_0008:stloc.1 // al
  IL_0009:ldloc。1 // al
  IL_000A:ldloc.0 // myInt
  IL_000B:ボックスSystem.Int32
  IL_0010:callvirt System.Collections.ArrayList.Add


ボックス(ボクシング)操作は、Int32型のヒープ上にオブジェクトを作成します。 タイプの構造の要素を追加すると、そのアナログがヒープ上に作成されるたびに、リンクがコレクションに分類されます。 時間が経つにつれて、一般的なコレクションが助けになりました。 例とそのIL表現を検討してください。



例2.コレクションの一般化の使用:



 System.Int32 myInt = 7; List<int> l = new List<int>(); l.Add(myInt);
      
      





このコードは次のように変換されます。



 IL_0002:stloc.0 // myInt
  IL_0003:newobj System.Collections.Generic.List..ctor
  IL_0008:stloc.1 // l
  IL_0009:ldloc。1 // l
  IL_000A:ldloc.0 // myInt
 IL_000B:callvirt System.Collections.Generic.List.Add


このようなコレクションはより高度であり、box \ unbox操作を使用せずに、値の型をより適切に処理できます。 これにより、メモリのオーバーヘッドが大幅に削減され、パフォーマンスが向上し、ガベージコレクションが削減されます。



しかし、しばらくの間コレクションをより詳細に実験した後、思いがけない瞬間に出会いました。 次のようなスタイルで何かを書く必要がある場合があります。



 IList l =新しいリスト<T>();


コードは単純ですが、構造に対する結果は混在していました。



そのようなコードのIL表現を見ると:



 System.Int32 myInt = 7;
  IList l = new List <int>();
  l.Add(myInt);


次に、以下を取得します。



  IL_0002:stloc.0 // myInt
  IL_0003:newobj System.Collections.Generic.List..ctor
  IL_0008:stloc.1 // l
  IL_0009:ldloc。1 // l
  IL_000A:ldloc.0 // myInt
  IL_000B:ボックスSystem.Int32
  IL_0010:callvirt System.Collections.IList.Add


私たちは再び包装ユニットに落ちます。 また、ヒープ上のオブジェクトをmyInt値のコピーとして取得します。 どうやら、開発者は、特に重要な型の場合、変数の一般化の型を明示的に指定することで、コレクションオブジェクトの動作に影響を与えるような方法でコレクションを実装しました。



これが何が起こっているのかを説明しようとした最初の結論でした。 その結果、著者自身から少し後に説明が見つかりました。 インターフェイス変数は常にヒープに配置する必要があり、これにより追加のパッキング操作が表示されます。



結論は簡単です。 通常はすべてが異なる方法で発生しますが、最初に理論、次に実践します。



All Articles