It's possible from IL, and it's possible to create a helper method for this that can be used from C#.
(可以从IL中获得,也可以为此创建一个辅助方法,该方法可以在C#中使用。)
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
static class CompareExchangeEnumImpl<T>
{
public delegate T dImpl(ref T location, T value, T comparand);
public static readonly dImpl Impl = CreateCompareExchangeImpl();
static dImpl CreateCompareExchangeImpl()
{
var underlyingType = Enum.GetUnderlyingType(typeof(T));
var dynamicMethod = new DynamicMethod(string.Empty, typeof(T), new[] { typeof(T).MakeByRefType(), typeof(T), typeof(T) });
var ilGenerator = dynamicMethod.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Ldarg_1);
ilGenerator.Emit(OpCodes.Ldarg_2);
ilGenerator.Emit(
OpCodes.Call,
typeof(Interlocked).GetMethod(
"CompareExchange",
BindingFlags.Static | BindingFlags.Public,
null,
new[] { underlyingType.MakeByRefType(), underlyingType, underlyingType },
null));
ilGenerator.Emit(OpCodes.Ret);
return (dImpl)dynamicMethod.CreateDelegate(typeof(dImpl));
}
}
public static class InterlockedEx
{
public static T CompareExchangeEnum<T>(ref T location, T value, T comparand)
{
return CompareExchangeEnumImpl<T>.Impl(ref location, value, comparand);
}
}
public enum Foo
{
X,
Y,
}
static class Program
{
static void Main()
{
Foo x = Foo.X;
Foo y = Foo.Y;
y = InterlockedEx.CompareExchangeEnum(ref x, y, Foo.X);
Console.WriteLine("x: " + x);
Console.WriteLine("y: " + y);
}
}
Output:
(输出:)
x: Y
y: X
This just forwards the arguments to the correct Interlocked.Exchange
overload.
(这只是将参数转发到正确的Interlocked.Exchange
重载。)
It fails badly if T
isn't really an enum type, or its underlying type doesn't have an Interlocked.Exchange
overload. (如果T
不是真正的枚举类型,或者它的基础类型没有Interlocked.Exchange
重载,则它将严重失败。)
The generated IL is verifiable, at least according to PEVerify, as can be checked by making this use AssemblyBuilder
and saving the result to a file.
(至少根据PEVerify可以验证生成的IL,可以通过使用AssemblyBuilder
并将结果保存到文件中进行检查。)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…