C# 在C中以正确的方式删除特权枚举标志#
我有一个用户权限的枚举类型,如下所示:C# 在C中以正确的方式删除特权枚举标志#,c#,.net,wpf,enums,C#,.net,Wpf,Enums,我有一个用户权限的枚举类型,如下所示: [Flags] public enum UserPrivileges : byte { None = 0, // 0000 0000 View = 1 << 0, // 0000 0001 Import = 1 << 1,
[Flags]
public enum UserPrivileges : byte
{
None = 0, // 0000 0000
View = 1 << 0, // 0000 0001
Import = 1 << 1, // 0000 0010
Export = 1 << 2, // 0000 0100
Supervisor = View | Import | Export | 1 << 3, // 0000 1111
Admin = Supervisor | 1 << 4 // 0001 1111
}
0001 1111 // Admin
0000 0111 // 7 flag
---------
0000 0111 // Remain only where 7 bit was set.
这对于在GUI中向用户显示和添加权限非常有效。它还可用于删除Superflag,如Supervisor(所有标志=
Supervisor都被删除,其他标志不变)
问题是,当我取消选中导入时,例如,我想删除所有超级标记(主管、管理员),但希望保留其他标记(查看、导出)
但我还没有想出一个好主意来实现这一点。任何一个对此有好办法的男孩?如果我知道你想要什么,这应该可以解决问题
byte tmp = 1 << 3 | 1 << 4;
byte removeSuperFlagMask = (byte) (~tmp);
byte notSuperflagsMask = 1 << 3 | 1 << 2 | 1 << 1;
if ((valueToRemove & notSuperflagsMask) != 0)
{
newValue = (byte)(removeSuperFlagMask & currentValue & ~valueToRemove);
}
byte tmp=1如果我理解正确,您希望删除Supervisor
和Admin
,因此:
UserPrivileges newPrivileges = (UserPrivileges)(((byte)currentPrivileges) & 7;
它将执行如下操作:
[Flags]
public enum UserPrivileges : byte
{
None = 0, // 0000 0000
View = 1 << 0, // 0000 0001
Import = 1 << 1, // 0000 0010
Export = 1 << 2, // 0000 0100
Supervisor = View | Import | Export | 1 << 3, // 0000 1111
Admin = Supervisor | 1 << 4 // 0001 1111
}
0001 1111 // Admin
0000 0111 // 7 flag
---------
0000 0111 // Remain only where 7 bit was set.
另一个例子
0000 0011 // View | Import
0000 0111 // 7 flag
---------
0000 0011 // Remain only where 7 bit was set.
“保留”的意思是,如果设置了7
标志,它将在结果中保留该值(beein0
或1
)。当7
标志为0
时,它将杀死0
的值,使我走上正确的道路,但它对我来说不够通用,因此我想出了另一个解决方案:
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
var mask = (byte)parameter;
if ((bool)value)
{
_targetValue |= mask;
}
else
{
if (IsSuperFlag(mask) && mask != 1)
_targetValue &= (byte)(mask >> 1);
else
{
// Get all flags from enum type that are no SuperFlags
var flags = Enum.GetValues(targetType).Cast<Enum>();
flags = flags.Where(x => !IsSuperFlag(System.Convert.ToByte(x)));
long nonSuperFlags = 0;
foreach (var flag in flags)
{
nonSuperFlags |= System.Convert.ToByte(flag);
}
// Now only remove everything except the nonSuperFlags
// and then remove the mask
_targetValue &= (byte)(~(_targetValue ^ nonSuperFlags | mask));
}
}
return Enum.Parse(targetType, _targetValue.ToString());
}
private bool IsSuperFlag(byte flag)
{
var b = flag;
b--;
b |= (byte)(b >> 1);
b |= (byte)(b >> 2);
b |= (byte)(b >> 4);
b |= (byte)(b >> 8);
return b == flag;
}
public object ConvertBack(对象值,类型targetType,
对象参数,CultureInfo(区域性)
{
变量掩码=(字节)参数;
如果((布尔)值)
{
_targetValue |=掩码;
}
其他的
{
如果(IsSuperFlag(掩码)&掩码!=1)
_targetValue&=(字节)(掩码>>1);
其他的
{
//从枚举类型中获取所有没有超标记的标记
var flags=Enum.GetValues(targetType.Cast();
flags=flags.Where(x=>!IsSuperFlag(System.Convert.ToByte(x));
长非超级标志=0;
foreach(标志中的var标志)
{
非超级标志|=System.Convert.ToByte(标志);
}
//现在只删除除非超级标志之外的所有内容
//然后取下面具
_targetValue&=(字节)(~(_targetValue^非超级标志|掩码));
}
}
返回Enum.Parse(targetType,_targetValue.ToString());
}
专用布尔IsSuperFlag(字节标志)
{
var b=标志;
b--;
b |=(字节)(b>>1);
b |=(字节)(b>>2);
b |=(字节)(b>>4);
b |=(字节)(b>>8);
返回b==标志;
}
我只是得到了枚举类型的所有非超级标记,它们只删除了超级标记,然后删除了标志。您是否试图避免使用条件逻辑?如果您开始使用If/else语句对其进行编码,这很简单。在您的示例中-您喜欢删除Admin
和Import
?嗯,您在这里滥用枚举,这给您带来了所有的麻烦。@Staeff:是的,但这里的问题是您试图将逻辑编码到枚举中。我想,这个问题与enum的定义有关,它将权限(查看、导入、导出)与角色(主管、管理员)混合在一起。谢谢你让我想到这个想法,但我需要一个更通用的解决方案。看看我的答案。这远远不是最好的办法。但既然你完成了你的目标,那就是问题所在。