简体   繁体   中英

How to apply InterLocked.Exchange for Enum Types in C#?

public enum MyEnum{Value1, Value2}  
class MyClass 
{ 
    private MyEnum _field;   
    public MyEnum Field  // added for convenience
    {
        get { return _field; }  
        set { Interlocked.Exchange(ref _field, value); // ERROR CS0452  }
    }  
} 

could be solved with:

 public enum MyEnum{Value1, Value2}  
 public class MyClass2  
 {  
   private int _field;  //change to int
   public MyEnum Field  // added for convenience
   { 
    get { return (MyEnum)_field; }
    set { System.Threading.Interlocked.Exchange(ref _field, (int)value); }
   }  
 }

Is there any better way for this problem?

Is there any better way for this problem?

If you need to use Interlocked.Exchange then this is the best way, in fact I think it is the only way to Exchange an enum.

The reason you get the compiler error is that the compiler thinks you want to use Exchange<T> , but T needs to be a reference type for this to work, since you are not using a reference type it fails. So, the best work around is to cast to an int as you have done, and thus force the compiler to use the non-generic Exchange(int, int) .

You appear to not need the "exchange" feature of Interlocked.Exchange, as you are ignoring its return value. Therefore I think the solution that might make you happiest is to mark _field as volatile:

private volatile MyEnum _field;

The Interlocked methods are fine. You could use a plain old lock , but that seems like overkill here. However, you are going to need to use a guarded read of some kind in the getter otherwise you may run into memory barrier issues. Since you are already using an Interlocked method in the setter it makes sense to do the same in the getter.

public MyEnum Field  // added for convenience
{ 
  get { return (MyEnum)Interlocked.CompareExchange(ref _field, 0, 0); }
  set { Interlocked.Exchange(ref _field, (int)value); }
}  

You could also get away with marking the field as volatile if you like.

Is there any better way for this problem?

I use a class instead of Enum:

public class DataCollectionManagerState
{
    public static readonly DataCollectionManagerState Off = new DataCollectionManagerState() { };
    public static readonly DataCollectionManagerState Starting = new DataCollectionManagerState() { };
    public static readonly DataCollectionManagerState On = new DataCollectionManagerState() { };

    private DataCollectionManagerState() { }

    public override string ToString()
    {
        if (this == Off) return "Off";
        if (this == Starting) return "Starting";
        if (this == On) return "On";

        throw new Exception();
    }
}

public class DataCollectionManager
{
    private static DataCollectionManagerState _state = DataCollectionManagerState.Off;

    public static void StartDataCollectionManager()
    {
        var originalValue = Interlocked.CompareExchange(ref _state, DataCollectionManagerState.Starting, DataCollectionManagerState.Off);
        if (originalValue != DataCollectionManagerState.Off)
        {
            throw new InvalidOperationException(string.Format("StartDataCollectionManager can be called when it's state is Off only. Current state is \"{0}\".", originalValue.ToString()));
        }

        // Start Data Collection Manager ...

        originalValue = Interlocked.CompareExchange(ref _state, DataCollectionManagerState.On, DataCollectionManagerState.Starting);
        if (originalValue != DataCollectionManagerState.Starting)
        {
            // Your code is really messy
            throw new Exception(string.Format("Unexpected error occurred. Current state is \"{0}\".", originalValue.ToString()));
        }
    }
}

Why not simply synchonrize the threading?

protected static object _lockObj = new object();

set
{
    lock(_lockObj)
    {
         _field = value;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM