Search code examples
c#.netenumspass-by-referenceinterlocked

How to convert a ref [enum type] to a ref int?


I want to use Interlocked.CompareExchange with an enum type that inherits from int, like so:

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");
        }
    }
}

However, CompareExchange only works with reference types and select value types (see here). Since a MyEnum is really an int underneath the skin, I thought I should be able to pass it as a ref int:

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

However, this doesn't seem to work either. I get the following error:

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

Casting before passing it in, e.g. ref (int)s_field, doesn't help either.

How can I fix this? Is there any way to use CompareExchange with enums, or must I use ints instead?


Solution

  • I believe this is now possible with the Unsafe class which was introduced in .NET Core. Run this to install the package containing the class into your app:

    Install-Package System.Runtime.CompilerServices.Unsafe
    

    In .NET 5+ this is built-in already.

    Then you can do:

    Interlocked.CompareExchange(ref Unsafe.As<MyEnum, int>(ref s_field), (int)MyEnum.B, (int)MyEnum.A)
    

    Note that this requires C# 7 language support for ref returns, so you need to have VS2017 or later.