“ volatileフィールドへの参照はvolatileとして扱われません”含意
-
06-07-2019 - |
質問
次のコード
using System.Threading;
class Test
{
volatile int counter = 0;
public void Increment()
{
Interlocked.Increment(ref counter);
}
}
次のコンパイラ警告を発生させます。
"A reference to a volatile field will not be treated as volatile"
この警告を出すために、ここで何か間違ったことをしていますか?コンパイラーがこれについて警告するのはなぜですか?
解決
あなたは何も悪いことをしていません。 ドキュメントによると:
volatileフィールドは通常はすべきではありません refまたはoutを使用して渡される パラメータ。 スコープ内で揮発性として扱われます 関数の。例外があります これに、たとえば インターロックされたAPI。
他のヒント
基本的に警告は、volatileフィールドを参照渡しすると、呼び出し側のコードはそれをvolatileで処理することを知らないということです。 Interlocked.Incrementの場合、メソッドの性質上、おそらく重要ではありませんが、Interlockedを使用している場合は、変数を揮発性にする必要はありませんとにかく。
一般に、この2つを混ぜることは避けたいと思います-Interlockedを使用している場合は、どこでも( Interlocked.CompareExchange(ref counter、0、0)
で読みます)。揮発性を個人的に非常に頻繁に使用しているとは言えません。シンプルなカウンターでは、インターロックを使用する可能性があります が、ほとんどのタスクでロックを使用する可能性が高くなります。
これを使用:
#pragma warning disable 420
// M
// dM
// MMr
// 4MMML .
// MMMMM. xf
// . "MMMMM .MM-
// Mh.. +MMMMMM .MMMM
// .MMM. .MMMMML. MMMMMh
// )MMMh. MMMMMM MMMMMMM
// 3MMMMx. 'MMMMMMf xnMMMMMM"
// '*MMMMM MMMMMM. nMMMMMMP"
// *MMMMMx "MMMMM\ .MMMMMMM=
// *MMMMMh "MMMMM" JMMMMMMP
// MMMMMM 3MMMM. dMMMMMM .
// MMMMMM "MMMM .MMMMM( .nnMP"
// =.. *MMMMx MMM" dMMMM" .nnMMMMM*
// "MMn... 'MMMMr 'MM MMM" .nMMMMMMM*"
// "4MMMMnn.. *MMM MM MMP" .dMMMMMMM""
// ^MMMMMMMMx. *ML "M .M* .MMMMMM**"
// *PMMMMMMhn. *x > M .MMMM**""
// ""**MMMMhx/.h/ .=*"
// .3P"%....
// nP" "*MMnx
if(Interlocked.CompareExchange(ref isLoaded, 1, 0) != 0)
return;
#pragma warning restore 420
フィールドを参照渡ししているため、エラーが発生しています。これが意味するのは、ターゲットメソッドがフィールドが volatile
としてマークされていることを認識していないため、そのように扱わないことです。
所属していません StackOverflow