インターフェイスにフィールドを含めることはできませんが、プロパティを含めることはできます。ほとんどの場合、プロパティはフィールドのように使用できます。次のように言うのは難しくありません。
インターフェイス ISomeProperties
{int prop1 {get;set;}; 文字列 prop2 {get; 設定;}}
インターフェイス IMoreProperties
{string prop3 {get;set;}; double prop4 {get; 設定;}}
インターフェイス ICombinedProperties : ISomeProperties、IMoreProperties;
{ }
type の保存場所が与えられたICombinedProperties
場合、4 つのプロパティすべてに直接、手間をかけずにアクセスできます。
ただし、フィールドでは実行できてプロパティでは実行できないことがいくつかあることに注意してください。たとえば、フィールドをInterlocked.Increment
プロパティに渡すことはできますが、渡すことはできません。Interlocked.Increment
プロパティを変数にコピーし、それを呼び出し、結果をプロパティにコピーして戻そInterlocked.Increment
うとすると、場合によっては「機能する」可能性がありますが、2 つのスレッドが同じことを同時に実行しようとすると失敗します (可能性があります)。たとえば、両方のスレッドが 5 の値を読み取り、それを 6 にインクリメントしてから 6 を書き戻しますInterlocked.Increment
が、最初は 5 に等しいフィールドで 2 つのスレッドを呼び出すと、7 が生成されることが保証されます)。
これを回避するには、インターフェイスに、フィールドでインターロックされたメソッドを実行するいくつかのメソッドを含める必要がある場合があります (たとえば、Interlocked.Increment
フィールドで呼び出して結果を返す関数を含めることができます)。ref
パラメータとしてフィールドを持つ指定されたデリゲート(例:
デリゲート void ActionByRef<T1>(ref T1 p1);
デリゲート void ActionByRef<T1,T2>(ref T1 p1, ref T2 p2);
デリゲート void ActionByRef<T1,T2,T3>(ref T1 p1, ref T2 p2, ref T3 p3);
インターフェイス IThing
{ // クライアント コードが T 型のフィールドを直接操作できるようにする必要があります。
void ActOnThing(ActionByRef<T> proc);
void ActOnThing<ExtraT1>(ActionByRef<T, ExtraT1> proc, ref ExtraT1 ExtraP1);
void ActOnThing<ExtraT1, ExtraT2>
(ActionByRef<T> proc, ref ExtraT1 ExtraP1, ref ExtraT2 ExtraP2);
}
インターフェースのインスタンスが与えられると、次のようなことができます:
theInstance.ActOnThing(
(ref int param) => Threading.Interlocked.Increment(ref param)
);
または、ローカル変数がmaskValue
ありxorValue
、フィールドをアトミックに更新したい場合field = (field & maskValue) ^ xorValue
:
theInstance.ActOnThing(
(ref int パラメータ、ref int MaskValue、ref int XorValue) => {
int oldValue,newValue;
do {oldValue = param; newValue = (oldValue & MaskValue) ^ XorValue;
while (Threading.Interlocked.CompareExchange(ref Param, newValue, oldValue) !=
古い値)、
ref maskValue、ref xorValue);
);
フィールドで実行したいアクションのタイプが数種類しかない場合は、単純にインターフェイス内に含めるのが最も簡単です。一方、上記のアプローチでは、クライアントが任意の一連のアクションを実行できるように、インターフェイスがそのフィールドを公開できます。