C#标志枚举按值或名称切换
我有一个标志C#标志枚举按值或名称切换,c#,enums,bit-manipulation,enum-flags,C#,Enums,Bit Manipulation,Enum Flags,我有一个标志enum,希望通过它的(long)值来切换一些值 我通过EF使用long字段将实际权限存储在数据库中,例如: public Permissions UsersPermissions { get; set; } 从客户端,我通过enum逐个获取值以切换正确的值,因此如果数据库字段包含 `Value1 | Value2 | Value3` 我得到一个4,我必须从用户权限中删除值3 如何通过其长版本获得正确的enum值 如何在UserPermissions字段中通过其长表示形式
enum
,希望通过它的(long
)值来切换一些值
我通过EF
使用long
字段将实际权限存储在数据库中,例如:
public Permissions UsersPermissions { get; set; }
从客户端,我通过enum
逐个获取值以切换正确的值,因此如果数据库字段包含
`Value1 | Value2 | Value3`
我得到一个4,我必须从用户权限中删除值3
- 如何通过其长版本获得正确的
值enum
- 如何在UserPermissions字段中通过其长表示形式切换一个值
我尝试了
usersPermissions |=permissionValue
,但它说我不能在long
和权限类型上使用=
运算符。必须在枚举上使用异或运算符。因此,如果您的权限值具有:
- 价值1
- 价值2
- 价值3
- 价值4
如果要删除值4,则必须执行以下操作:
var perm = Permissions.Value1 | Permissions.Value2 | Permissions.Value3 | Permissions.Value4;
perm = perm ^ Permissions.Value4;
必须对枚举执行异或运算符。因此,如果您的权限值具有:
- 价值1
- 价值2
- 价值3
- 价值4
如果要删除值4,则必须执行以下操作:
var perm = Permissions.Value1 | Permissions.Value2 | Permissions.Value3 | Permissions.Value4;
perm = perm ^ Permissions.Value4;
您必须在适当的位置对long
和Permissions
进行强制转换,如下所示:
Permissions perms = Permissions.Value1 | Permissions.Value2 | Permissions.Value3;
Console.WriteLine(perms); // Value1, Value2, Value3
long toRemove = 4;
// OR: long toRemove = (long) Permissions.Value3;
perms = (Permissions) ((long)perms & ~toRemove); // Use "& ~X" to remove bits set in X.
Console.WriteLine(perms); // Value1, Value2
这里重要的一点是,~toRemove
返回toRemove
的按位补码,从而为您提供一组位标志,您可以使用原始值&
关闭在toRemove
中设置的所有位
您必须将perms
转换为long
,才能执行此&
操作
最后,通过&
获得所需的结果后,您有一个long
,您必须将其转换回权限
,以获得正确的枚举类型作为最终答案。您必须在适当的点对long
和权限
进行转换,如下所示:
Permissions perms = Permissions.Value1 | Permissions.Value2 | Permissions.Value3;
Console.WriteLine(perms); // Value1, Value2, Value3
long toRemove = 4;
// OR: long toRemove = (long) Permissions.Value3;
perms = (Permissions) ((long)perms & ~toRemove); // Use "& ~X" to remove bits set in X.
Console.WriteLine(perms); // Value1, Value2
这里重要的一点是,~toRemove
返回toRemove
的按位补码,从而为您提供一组位标志,您可以使用原始值&
关闭在toRemove
中设置的所有位
您必须将perms
转换为long
,才能执行此&
操作
最后,通过&
获得所需的结果后,您有一个长
,您必须返回到权限
,以获得正确的枚举类型作为最终答案。据我所知,您的输入是一个数字,您希望它是一个权限
。好吧,你可以从字面上投射它,即使它不是一个离散值。如果它是其中一个标志值的组合,那么这甚至可以“仅仅计算出”。C#枚举以这种方式进行强制转换非常聪明
下面是一个代码示例,可以实现您想要的功能
[Flags]
public enum TestEnum : long
{
ValueNone = 0, // You can't really "have" a Value0, it's an absence of values
Value1 = 0x1,
Value2 = 0x2,
Value3 = 0x4,
Value4 = 0x8
}
foreach(var enumVal in Enum.GetValues(typeof(TestEnum)))
{
Console.WriteLine("val is: {0} long is: {1}", enumVal, (long)enumVal);
}
{
Console.WriteLine("Start with 1 and 3, remove 3 from number");
var testEnum = TestEnum.Value1 | TestEnum.Value3;
Console.WriteLine("testEnum is: {0}({1})", testEnum, (long)testEnum);
long testVal = 4; // TestEnum.Value3
var removeEnum = (TestEnum)testVal;
removeEnum = ~removeEnum;
testEnum &= removeEnum;
Console.WriteLine("testEnum is: {0}({1})", testEnum, (long)testEnum);
}
{
Console.WriteLine("Start with 1, 2, 4 and remove 1 and 4 from number");
var testEnum = TestEnum.Value1 | TestEnum.Value2 | TestEnum.Value4;
Console.WriteLine("testEnum is: {0}({1})", testEnum, (long)testEnum);
long testVal = (long)TestEnum.Value1 | (long)TestEnum.Value4; // Could also have added them
var removeEnum = (TestEnum)testVal;
Console.WriteLine("Removing: {0}({1})", removeEnum, (long)removeEnum);
testEnum &= ~removeEnum;
Console.WriteLine("testEnum is: {0}({1})", testEnum, (long)testEnum);
}
下面是一种通过最后一个元素的值获取枚举限制的方法:
{
// Check the value to see what the range of the enumeration is
var lastVal = Enum.GetValues(typeof(TestEnum)).Cast<TestEnum>().Last();
long limit = (long)lastVal * 2;
Console.WriteLine("Limit of flags for TestEnum is: " + limit);
Func<long, bool> testLambda = x => x < limit;
Console.WriteLine("Value of {0} within limit: {1}", 14, testLambda(14));
Console.WriteLine("Value of {0} within limit: {1}", 16, testLambda(16));
Console.WriteLine("Value of {0} within limit: {1}", 200, testLambda(200));
Console.WriteLine("Value of {0} within limit: {1}", 0, testLambda(0));
Console.WriteLine("Out of range looks like: " + (TestEnum)17);
Console.WriteLine("In range looks like: " + (TestEnum)14);
}
我完全承认上面可能有更好的方法,但从根本上说,如果您有一个[Flags]
enum,因此其中的所有内容都在一定程度上是“有效的”(所有组合都很好),只需检查您的值是否超出范围,然后将其从整数类型直接转换为enum类型,并将其终止。一旦它是您的标志类型,您就可以使用位运算符了。没问题,所以请先这样做。从我所知道的情况来看,您的输入是一个数字,您希望它是一个权限。好吧,你可以从字面上投射它,即使它不是一个离散值。如果它是其中一个标志值的组合,那么这甚至可以“仅仅计算出”。C#枚举以这种方式进行强制转换非常聪明
下面是一个代码示例,可以实现您想要的功能
[Flags]
public enum TestEnum : long
{
ValueNone = 0, // You can't really "have" a Value0, it's an absence of values
Value1 = 0x1,
Value2 = 0x2,
Value3 = 0x4,
Value4 = 0x8
}
foreach(var enumVal in Enum.GetValues(typeof(TestEnum)))
{
Console.WriteLine("val is: {0} long is: {1}", enumVal, (long)enumVal);
}
{
Console.WriteLine("Start with 1 and 3, remove 3 from number");
var testEnum = TestEnum.Value1 | TestEnum.Value3;
Console.WriteLine("testEnum is: {0}({1})", testEnum, (long)testEnum);
long testVal = 4; // TestEnum.Value3
var removeEnum = (TestEnum)testVal;
removeEnum = ~removeEnum;
testEnum &= removeEnum;
Console.WriteLine("testEnum is: {0}({1})", testEnum, (long)testEnum);
}
{
Console.WriteLine("Start with 1, 2, 4 and remove 1 and 4 from number");
var testEnum = TestEnum.Value1 | TestEnum.Value2 | TestEnum.Value4;
Console.WriteLine("testEnum is: {0}({1})", testEnum, (long)testEnum);
long testVal = (long)TestEnum.Value1 | (long)TestEnum.Value4; // Could also have added them
var removeEnum = (TestEnum)testVal;
Console.WriteLine("Removing: {0}({1})", removeEnum, (long)removeEnum);
testEnum &= ~removeEnum;
Console.WriteLine("testEnum is: {0}({1})", testEnum, (long)testEnum);
}
下面是一种通过最后一个元素的值获取枚举限制的方法:
{
// Check the value to see what the range of the enumeration is
var lastVal = Enum.GetValues(typeof(TestEnum)).Cast<TestEnum>().Last();
long limit = (long)lastVal * 2;
Console.WriteLine("Limit of flags for TestEnum is: " + limit);
Func<long, bool> testLambda = x => x < limit;
Console.WriteLine("Value of {0} within limit: {1}", 14, testLambda(14));
Console.WriteLine("Value of {0} within limit: {1}", 16, testLambda(16));
Console.WriteLine("Value of {0} within limit: {1}", 200, testLambda(200));
Console.WriteLine("Value of {0} within limit: {1}", 0, testLambda(0));
Console.WriteLine("Out of range looks like: " + (TestEnum)17);
Console.WriteLine("In range looks like: " + (TestEnum)14);
}
我完全承认上面可能有更好的方法,但从根本上说,如果您有一个[Flags]
enum,因此其中的所有内容都在一定程度上是“有效的”(所有组合都很好),只需检查您的值是否超出范围,然后将其从整数类型直接转换为enum类型,并将其终止。一旦它是您的标志类型,您就可以使用按位运算符了。没问题,所以请先这样做。我的问题是,我得到的是一个长值,而不是权限。值4。这就是为什么按位运算符不能以这种方式工作。如何才能说枚举的类型是long,而这正是在中心下使用的类型,因此您需要执行一些强制转换-perm=(perm=(Permissions)((long)perm^(long)4)我的问题是,我得到的是一个长值,而不是权限。Value4。这就是为什么按位运算符不能以这种方式工作。在您的例子中,枚举的类型是long,这是在中心下使用的类型,因此您需要执行一些强制转换-perm=(权限)((long)perm^(long)4)这是否回答了您的问题?我想,你应该使用&
和~
,就像附件中指出的那样。这是否回答了你的问题?我想,你应该使用&
和~
,就像附件中指出的那样