次のプログラムがあるとします。
using System;
namespace VS2012TestApp
{
class Program
{
[Flags]
public enum IoStatus : byte
{
ControlStore = (byte)128,
Control = (byte)64,
LogicalState = (byte)32,
PhysicalState = (byte)16,
NewEdge = (byte)4,
Overload = (byte)2,
NoLoad = (byte)1,
None = (byte)0,
Notify = (byte)8,
}
private static IoStatus Status = IoStatus.LogicalState;
static void Main(string[] args)
{
Process(IoStatus.LogicalState | IoStatus.Overload, IoStatus.None);
}
private static void Process(IoStatus bitsSet, IoStatus bitsCleared)
{
bitsSet |= Status;
bitsCleared |= ~Status;
// Console.WriteLine("set {0}, clear {1}", bitsSet, bitsCleared);
bitsSet &= ~(IoStatus.LogicalState | IoStatus.PhysicalState);
bitsCleared &= ~(IoStatus.LogicalState | IoStatus.PhysicalState);
Console.WriteLine("set {0}, clear {1}", bitsSet, bitsCleared);
}
}
}
デバッグ モードの Win7 x64 ビットの VS2012 (アップデート 3) では、次のようになります。
オーバーロードの設定、NoLoad のクリア、オーバーロード、NewEdge、Notify、Control、ControlStore
これは私が期待するものです。
リリース モード (最適化がオンの場合とオフの場合):
過負荷を設定し、なしをクリアします
これは間違っています。
ターゲット プラットフォームの AnyCPU または x86 は、どちらも同じ出力になります。このコードは、VS2008 のデバッグおよびリリース モードで正常に動作します。VS2010 は試していません。
編集:リリースモードでデバッガーで実行すると、正しい動作が生成されます。
次のいずれかの方法で修正できます。
- (現在コメントアウトされている)の挿入
Console.WriteLine()
enum
toのバッキング タイプの変更int
のコードを次のように変更します
Process
。private static void Process(IoStatus bitsSet, IoStatus bitsCleared) { bitsSet = (bitsSet | Status) & ~(IoStatus.LogicalState | IoStatus.PhysicalState); bitsCleared = (bitsCleared | ~Status) & ~(IoStatus.LogicalState | IoStatus.PhysicalState); Console.WriteLine("Set {0}, Clear {1}", bitsSet, bitsCleared); }
問題は、意図しない方法で列挙型を使用していて、単に「未定義の動作」に遭遇したのか、それともコンパイラ/ジッターのバグなのかということです。