免責事項: 私の投稿は明らかに常に冗長です。タイトルの質問に対する答えをたまたま知っている場合は、以下の詳細な説明を読まずに、自由に答えてください。
このSystem.Threading.Interlocked
クラスは、スレッドセーフなコードの記述を支援する非常に便利なメソッドをいくつか提供します。より複雑なメソッドの 1 つに がありますCompareExchange
。これは、複数のスレッドから更新される可能性のある実行中の合計を計算するために使用できます。
の使用はCompareExchange
少しトリッキーなので、いくつかのヘルパー メソッドを提供するのはかなり常識的な考えだと思いました。
// code mangled so as not to require horizontal scrolling
// (on my monitor, anyway)
public static double Aggregate
(ref double value, Func<double, double> aggregator) {
double initial, aggregated;
do {
initial = value;
aggregated = aggregator(initial);
} while (
initial != Interlocked.CompareExchange(ref value, aggregated, initial)
);
return aggregated;
}
public static double Increase(ref double value, double amount) {
return Aggregate(ref value, delegate(double d) { return d + amount; });
}
public static double Decrease(ref double value, double amount) {
return Aggregate(ref value, delegate(double d) { return d - amount; });
}
さて、おそらく私はジェネリックに満足しているという罪を犯しているだけです(認めますが、これは多くの場合真実です)。しかし、上記のメソッドによって提供される機能を値のみに制限するのはばかげているように感じdouble
ます (または、より正確には、サポートしたいすべての型に対して上記のメソッドのオーバーロードされたバージョンを作成する必要があります)。なぜ私はこれを行うことができないのですか?
// the code mangling continues...
public static T Aggregate<T>
(ref T value, Func<T, T> aggregator) where T : IEquatable<T> {
T initial, aggregated;
do {
initial = value;
aggregated = aggregator(initial);
} while (
!initial.Equals(
Interlocked.CompareExchange<T>(ref value, aggregated, initial)
)
);
}
Interlocked.CompareExchange<T>
どうやらwhere T : class
制約があるため、これを行うことはできません。理由がわかりません。つまり、accept 、、などのオーバーロードが既に存在するためかもしれません。しかし、それは正当な理由とは思えません。たとえば、私の場合、このメソッドを使用してさまざまな原子計算を実行できると非常に便利です。CompareExchange
Int32
Int64
Double
Aggregate<T>