構造型のメンバをフィールドではなくプロパティとして公開すると、特に構造が「風変わりなオブジェクト」ではなく構造として実際に扱われる場合、パフォーマンスとセマンティクスが低下することがよくあります。
.NETの構造は、一緒にダクトでテーピングされたフィールドのコレクションであり、いくつかの目的のためにユニットとして扱うことができます。.NET Frameworkは、クラスオブジェクトとほぼ同じ方法で構造を使用できるように設計されており、便利な場合があります。
構造を取り巻くアドバイスの多くは、プログラマが構造をフィールドの集合としてではなくオブジェクトとして使用したいという考えに基づいています。一方、テープでまとめられたフィールドのように動作するものがあると便利な場合が多くあります。それが必要な場合、.NETのアドバイスはプログラマーとコンパイラーに不必要な作業を追加し、構造を直接使用するよりもパフォーマンスとセマンティクスを悪化させます。
構造体を使用する際に留意すべき最大の原則は次のとおりです。
構造体を値で渡したり戻したりしないでください。そうしないと、不必要にコピーされてしまいます。
原則#1が順守されている場合、大きな構造は小さな構造と同様に機能します。
場合はAlphablob
26個の公共含む構造であるint
AZという名前のフィールドを、およびプロパティのゲッターab
その和を返すa
とb
フィールドを、そして与えられAlphablob[] arr; List<Alphablob> list;
、コードは、int foo = arr[0].ab + list[0].ab;
フィールドを読む必要があるだろうa
とb
のarr[0]
、しかし、すべての26の分野読む必要があるでしょうlist[0]
でもそれは意志かかわらをそれらの2つを除くすべてを無視します。のような構造で効率的に動作できる一般的なリストのようなコレクションがalphaBlob
必要な場合は、インデックス付きゲッターをメソッドに置き換える必要があります。
delegate ActByRef<T1,T2>(ref T1 p1, ref T2 p2);
actOnItem<TParam>(int index, ActByRef<T, TParam> proc, ref TParam param);
それは次に起動しproc(ref backingArray[index], ref param);
ます。1置き換えた場合には、そのようなコレクションを考えるsum = myCollection[0].ab;
と
int result;
myCollection.actOnItem<int>(0,
ref (ref alphaBlob item, ref int dest)=>dest = item,
ref result);
これによりalphaBlob
、プロパティゲッターで使用されない部分をコピーする必要がなくなります。渡されたデリゲートはそのref
パラメータ以外にはアクセスしないため、コンパイラは静的デリゲートを渡すことができます。
残念ながら、.NET Frameworkは、このことをうまく機能させるために必要なデリゲートの種類を定義しておらず、構文は最終的には混乱の種になります。一方、このアプローチにより、構造を不必要にコピーすることを回避できます。これにより、配列に格納された大きな構造に対してインプレースアクションを実行することが実用的になります。これはストレージにアクセスする最も効率的な方法です。