【发布时间】:2018-12-26 07:45:34
【问题描述】:
我想要一种快速通用的方法来检查标有FlagsAttribute 的枚举值是否有效。为此,我创建了一个名为EnumInfo<T> 的类,它通过按位或运算枚举的所有不同值来计算其静态构造函数中的标志模式。然后,IsValidFlagsValue 方法只需通过与标志模式执行按位与比较来检查提供的值。
考虑以下 C# 代码
// This code requires C# 7.3
public static class EnumInfo<T> where T : Enum, IConvertible
{
// This field is calculated in the static constructor
public static readonly ulong FlagsPattern;
public static bool IsValidFlagsValue(this T enumValue)
{
// The actual problem is here: ToUInt64 allocates (because of internal boxing?)
var convertedUInt64Value = enumValue.ToUInt64(null);
return (FlagsPattern & convertedUInt64Value) == convertedUInt64Value;
}
}
我的实际问题如下:为了重用这段代码,我将枚举值转换为类型ulong。但是,enumValue.ToUInt64(null) 在内部分配 24 字节,正如在以下基准测试中所见(使用 BenchmarkDotNet 执行):
public class ToUInt64Benchmark
{
public IConvertible FlagsValue =
BindingFlags.Public | BindingFlags.Instance;
[Benchmark]
public ulong EnumToUInt64() => FlagsValue.ToUInt64(null);
}
目前有什么方法可以避免这种分配吗?我尝试使用不安全的代码,但我无法获取通用值的地址(即&enumValue 不起作用)。有没有其他我没有想到的方法?
提前感谢您的帮助。
【问题讨论】:
-
将泛型限制为
struct, Enum(不需要IConvertible),然后也许使用Unsafe(类不是关键字)。还看到了 Enums.net 项目。他使用了一个很酷的技巧来将枚举转换为积分,但是它使用 fody (il rewriting) 来生成该方法的主体 -
@pinkfloydx33 你是我的英雄!详情见我的回答。
标签: c# performance memory enums garbage-collection