如何将ref [enum类型]转换为ref int?

时间:2016-07-06 19:53:16

标签: c# .net enums pass-by-reference interlocked

我想将Interlocked.CompareExchange与继承自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);

然而,这似乎也不起作用。我收到以下错误:

  

错误CS1503:参数1:无法从'ref MyEnum'转换为'ref int'

在传入之前进行铸造,例如ref (int)s_field,也无济于事。

我该如何解决这个问题?有没有办法将CompareExchange用于枚举,或者我必须使用整数?

4 个答案:

答案 0 :(得分:0)

你想使用union吗?

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

当然,这有点麻烦......

答案 1 :(得分: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");

答案 2 :(得分: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; }

答案 3 :(得分:0)

我相信现在可以使用.NET Core中引入的Unsafe类。运行此命令将包含该类的包安装到您的应用程序中:

Install-Package System.Runtime.CompilerServices.Unsafe

然后你可以Interlocked.CE(ref Unsafe.As<MyEnum, int>(ref s_field), (int)MyEnum.B, (int)MyEnum.A)。请注意,这需要C#7语言支持ref返回,因此您需要使用VS2017或更高版本。