如何将 ref [枚举类型] 转换为 ref int?
How to convert a ref [enum type] to a ref int?
我想将 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
仅适用于引用类型和 select 值类型(参见 here)。由于 MyEnum
实际上是皮肤下的一个整数,我想我应该能够将它作为一个 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
与枚举一起使用,还是我必须改用整数?
您想使用联合吗?
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");
}
当然,有点繁琐...
评估后转换值呢?
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");
也许你可以使用:
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; }
.
我相信现在可以使用 .NET Core 中引入的 Unsafe
class。 运行 将包含 class 的软件包安装到您的应用中:
Install-Package System.Runtime.CompilerServices.Unsafe
那你就可以Interlocked.CE(ref Unsafe.As<MyEnum, int>(ref s_field), (int)MyEnum.B, (int)MyEnum.A)
了。请注意,这需要对 ref returns 的 C# 7 语言支持,因此您需要拥有 VS2017 或更高版本。
我想将 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
仅适用于引用类型和 select 值类型(参见 here)。由于 MyEnum
实际上是皮肤下的一个整数,我想我应该能够将它作为一个 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
与枚举一起使用,还是我必须改用整数?
您想使用联合吗?
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");
}
当然,有点繁琐...
评估后转换值呢?
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");
也许你可以使用:
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; }
.
我相信现在可以使用 .NET Core 中引入的 Unsafe
class。 运行 将包含 class 的软件包安装到您的应用中:
Install-Package System.Runtime.CompilerServices.Unsafe
那你就可以Interlocked.CE(ref Unsafe.As<MyEnum, int>(ref s_field), (int)MyEnum.B, (int)MyEnum.A)
了。请注意,这需要对 ref returns 的 C# 7 语言支持,因此您需要拥有 VS2017 或更高版本。