2016-07-06 8 views
0

私はそうのように、int型から継承する列挙型でInterlocked.CompareExchangeを使用したい:ref [enum type]をref intに変換するには?

public enum MyEnum : int { A, B } 

public class MyClass 
{ 
    private static readonly MyEnum s_field = MyEnum.A; 

    public void Foo() 
    { 
     if (Interlocked.CompareExchange(ref s_field, MyEnum.B, MyEnum.A) == MyEnum.A) 
     { 
      Console.WriteLine("Changed from A to B"); 
     } 
    } 
} 

しかし、CompareExchangeは、参照のみのタイプを選択した値の型(hereを参照)で動作します。 MyEnumは本当に皮膚の下にint型ですので、私はREF int型としてそれを渡すことができるはずと思った:

// should call CompareExchange(ref int, int, int) overload 
Interlocked.CompareExchange(ref s_field, (int)MyEnum.B, (int)MyEnum.A); 

しかし、これはどちらか動作するようには思えません。それを渡す前に、キャスティング

Error CS1503: Argument 1: cannot convert from 'ref MyEnum' to 'ref int'

、例えば:私は次のエラーを取得しますref (int)s_fieldも役に立ちません。

どうすればこの問題を解決できますか?列挙型でCompareExchangeを使用する方法はありますか、代わりにintを使用する必要がありますか?

+0

enumを使用する具体的な理由はありますか? 「連動している」という言葉は、このように数に制限されています...定数で作業することはできますか(私は知っています...デザインのにおいはしますが)? –

+0

@AndreasNiedermairええ、私はちょうどコードがenumsでよりよく見えると思う。 –

+0

'Interlocked'はAPIの' enum'バリアントを提供しないので、あなたが望むことはできません。 'int'を使う必要があります。 – GreatAndPowerfulOz

答えて

0

.NETコアで導入されたUnsafeクラスではこれが可能だと思います。アプリにクラスを含むパッケージをインストールするためにこれを実行します。

Install-Package System.Runtime.CompilerServices.Unsafe 

次にあなたがInterlocked.CE(ref Unsafe.As<MyEnum, int>(ref s_field), (int)MyEnum.B, (int)MyEnum.A)を行うことができます。これにはref returnにC#7言語サポートが必要なので、VS2017以降が必要です。

0

ユニオンを使用しますか?もちろん

public enum MyEnum : int { A, B } 

[StructLayout(LayoutKind.Explicit)] 
struct IntEnumUnion 
{ 
    [FieldOffset(0)] 
    public MyEnum Enum; 
    [FieldOffset(0)] 
    public int Int; 
} 

private static IntEnumUnion s_field; 
s_field.Enum = MyEnum.A; 

if (Interlocked.CompareExchange(ref s_field.Int, (int)MyEnum.B, (int)MyEnum.A) 
    == (int)MyEnum.A) 
{ 
    Console.WriteLine("Changed from A to B"); 
} 

、それは

0

どう評価後の値の変換について...少し面倒ですか?

 int value = (int)MyEnum.A; 

     var result = Interlocked.CompareExchange(ref value, (int)MyEnum.A, (int)MyEnum.B); 

     if((MyEnum)result == MyEnum.A) 
      System.Console.WriteLine("Changed from A to B"); 
0

たぶんあなただけ使用することができます。

static readonly object lockInstance = new object(); 

public static TSimple CompareExchange<TSimple>(ref TSimple location1, TSimple value, TSimple comparand) 
{ 
    lock (lockInstance) 
    { 
    var location1Read = location1; 
    if (EqualityComparer<TSimple>.Default.Equals(location1Read, comparand)) 
    { 
     // location1 write 
     location1 = value; 
    } 
    return location1Read; 
    } 
} 

注意:lock事が唯一のこの特定の方法てを発生location1への変更を防止します。メソッドが実行されている間に他のスレッドがlocation1を操作できないようにすることはできません。これが問題の場合は、intを使用し、public static class MyEnum { public const int A = 0; public const int B = 1; }としてください。

関連する問題