我想将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
用于枚举,或者我必须使用整数?
答案 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或更高版本。