C# 优化大量枚举比较
C# Optimizing mass enum comparison
有没有办法优化下面的代码:
enum ObjType
{
A,
B,
C,
D,
E,
F,
G,
H
}
...
if (instance.ObjType == ObjType.B
|| instance.ObjType == ObjType.D
|| instance.ObjType == ObjType.E
|| instance.ObjType == ObjType.F
|| instance.ObjType == ObjType.G
|| instance.ObjType == ObjType.H)
doSmth();
以下解决方案不适合我:
if (instance.ObjType >= ObjType.B)
doSmth();
因为不同的情况需要大量比较ObjType的不同组合。
一般来说,你的代码没有问题。这是惯用的 C#。
如果 "optimize" 是指 "get rid of all the redundancy",我建议如下:
var relevantTypes = new[] { ObjType.B, ObjType.D, ObjType.E, ... };
if (relevantTypes.Contains(instance.ObjType))
doSmth();
局部变量只是一个示例,就我个人而言,我会将其设为 private static readonly
字段(因为您不能拥有 const
数组)。
如果您明智地选择名称,这也将使您的代码自文档化:
if (FooableTypes.Contains(instance.ObjType))
doSmth();
if (TypesComparableToBar.Contains(instance.ObjType))
doSmthElse();
如果您像这样手动分配值
enum ObjType
{
A = 1,
B = 2,
C = 3,
...
H = 8
}
您将能够使用数字比较。
同样,如果您使用枚举标志,您将能够使用位掩码:
[Flags]
enum ObjType
{
A = 1,
B = 2,
C = 4,
...
H = 256
}
if (((ObjType.A | ObjType.B | ObjType.C) & val) != 0) {
...
}
如果您必须经常进行这种比较并且希望使其更具可读性,那么一种可能的解决方案是扩展方法
public static IsBDEFGH(this ObjType oType)
{
return oType == ObjType.B
|| oType == ObjType.D
|| oType == ObjType.E
|| oType == ObjType.F
|| oType == ObjType.G
|| oType == ObjType.H;
}
然后像这样使用它
if(instance.ObjType.IsBDEFGH())
{
}
选择一个好名字,可以清楚地表明比较的值是什么。
您可以将枚举定义为标记枚举
[Flags]
enum ObjType
{
None = 0,
A = 1 << 0,
B = 1 << 1,
C = 1 << 2,
D = 1 << 3,
E = 1 << 4,
F = 1 << 5,
G = 1 << 6,
H = 1 << 7,
MyCombination1 = A | B | D,
MyCombination2 = C | F | G | H
}
这样您最多可以定义 32 个值(加上 None = 0
和任意数量的其他值组合)或最多 64 个值
[Flags]
enum ObjType : long
{
None = 0,
A = 1L << 0,
B = 1L << 1,
...
}
现在你可以比较
if (instance.ObjType & ObjType.MyCombination1 != ObjType.None) {
...
}
如果更适合您的需要,您也可以在枚举本身之外定义常量
private const ObjType AdHocCombination = ObjType.A | ObjType.C | ObjType.H;
定义标志时,值必须是 2 的幂(None
除外)。这可以通过使用左移运算符 <<
.
轻松实现
根据您的需要,您可以使用 [Flags]
如下:
[Flags]
enum ObjType
{
SomethingSpecial = 1 << 0,
SomethingSpecialElse = 1 << 1,
A = (1 << 16),
B = (1 << 17) | ObjType.SomethingSpecial,
C = (1 << 18) | ObjType.SomethingSpecialElse,
D = (1 << 19) | ObjType.SomethingSpecial | ObjType.SomethingSpecialElse,
}
然后您可以使用 HasFlag
方法:
ObjType.A.HasFlag(ObjType.SomethingSpecial); // false
ObjType.A.HasFlag(ObjType.SomethingSpecialElse); // false
ObjType.B.HasFlag(ObjType.SomethingSpecial); // true
ObjType.B.HasFlag(ObjType.SomethingSpecialElse); // false
ObjType.C.HasFlag(ObjType.SomethingSpecial); // false
ObjType.C.HasFlag(ObjType.SomethingSpecialElse); // true
ObjType.D.HasFlag(ObjType.SomethingSpecial); // true
ObjType.D.HasFlag(ObjType.SomethingSpecialElse); // true
有没有办法优化下面的代码:
enum ObjType
{
A,
B,
C,
D,
E,
F,
G,
H
}
...
if (instance.ObjType == ObjType.B
|| instance.ObjType == ObjType.D
|| instance.ObjType == ObjType.E
|| instance.ObjType == ObjType.F
|| instance.ObjType == ObjType.G
|| instance.ObjType == ObjType.H)
doSmth();
以下解决方案不适合我:
if (instance.ObjType >= ObjType.B)
doSmth();
因为不同的情况需要大量比较ObjType的不同组合。
一般来说,你的代码没有问题。这是惯用的 C#。
如果 "optimize" 是指 "get rid of all the redundancy",我建议如下:
var relevantTypes = new[] { ObjType.B, ObjType.D, ObjType.E, ... };
if (relevantTypes.Contains(instance.ObjType))
doSmth();
局部变量只是一个示例,就我个人而言,我会将其设为 private static readonly
字段(因为您不能拥有 const
数组)。
如果您明智地选择名称,这也将使您的代码自文档化:
if (FooableTypes.Contains(instance.ObjType))
doSmth();
if (TypesComparableToBar.Contains(instance.ObjType))
doSmthElse();
如果您像这样手动分配值
enum ObjType
{
A = 1,
B = 2,
C = 3,
...
H = 8
}
您将能够使用数字比较。
同样,如果您使用枚举标志,您将能够使用位掩码:
[Flags]
enum ObjType
{
A = 1,
B = 2,
C = 4,
...
H = 256
}
if (((ObjType.A | ObjType.B | ObjType.C) & val) != 0) {
...
}
如果您必须经常进行这种比较并且希望使其更具可读性,那么一种可能的解决方案是扩展方法
public static IsBDEFGH(this ObjType oType)
{
return oType == ObjType.B
|| oType == ObjType.D
|| oType == ObjType.E
|| oType == ObjType.F
|| oType == ObjType.G
|| oType == ObjType.H;
}
然后像这样使用它
if(instance.ObjType.IsBDEFGH())
{
}
选择一个好名字,可以清楚地表明比较的值是什么。
您可以将枚举定义为标记枚举
[Flags]
enum ObjType
{
None = 0,
A = 1 << 0,
B = 1 << 1,
C = 1 << 2,
D = 1 << 3,
E = 1 << 4,
F = 1 << 5,
G = 1 << 6,
H = 1 << 7,
MyCombination1 = A | B | D,
MyCombination2 = C | F | G | H
}
这样您最多可以定义 32 个值(加上 None = 0
和任意数量的其他值组合)或最多 64 个值
[Flags]
enum ObjType : long
{
None = 0,
A = 1L << 0,
B = 1L << 1,
...
}
现在你可以比较
if (instance.ObjType & ObjType.MyCombination1 != ObjType.None) {
...
}
如果更适合您的需要,您也可以在枚举本身之外定义常量
private const ObjType AdHocCombination = ObjType.A | ObjType.C | ObjType.H;
定义标志时,值必须是 2 的幂(None
除外)。这可以通过使用左移运算符 <<
.
根据您的需要,您可以使用 [Flags]
如下:
[Flags]
enum ObjType
{
SomethingSpecial = 1 << 0,
SomethingSpecialElse = 1 << 1,
A = (1 << 16),
B = (1 << 17) | ObjType.SomethingSpecial,
C = (1 << 18) | ObjType.SomethingSpecialElse,
D = (1 << 19) | ObjType.SomethingSpecial | ObjType.SomethingSpecialElse,
}
然后您可以使用 HasFlag
方法:
ObjType.A.HasFlag(ObjType.SomethingSpecial); // false
ObjType.A.HasFlag(ObjType.SomethingSpecialElse); // false
ObjType.B.HasFlag(ObjType.SomethingSpecial); // true
ObjType.B.HasFlag(ObjType.SomethingSpecialElse); // false
ObjType.C.HasFlag(ObjType.SomethingSpecial); // false
ObjType.C.HasFlag(ObjType.SomethingSpecialElse); // true
ObjType.D.HasFlag(ObjType.SomethingSpecial); // true
ObjType.D.HasFlag(ObjType.SomethingSpecialElse); // true