C#:获取按位枚举中的最小值键

C#:获取按位枚举中的最小值键,c#,enums,bitwise-operators,C#,Enums,Bitwise Operators,我有这样的枚举 [Flags] public enum Key { None = 0, A = 1, B = 2, C = 4 } 我有以下几点 Key k1 = Key.A | Key.B | Key.C; 我想得到k1中具有最小值的键。我该怎么做 例如: Key k1 = Key.A | Key.B | Key.C; // I want a Key k2 = Key.B | Key.C; // I want b Key k3 = Key.A | Key.C; // I

我有这样的枚举

[Flags]
public enum Key
{
  None = 0,
  A = 1,
  B = 2,
  C = 4
}
我有以下几点

Key k1 = Key.A | Key.B | Key.C;
我想得到k1中具有最小值的键。我该怎么做

例如:

Key k1 = Key.A | Key.B | Key.C; // I want a 
Key k2 = Key.B | Key.C; // I want b
Key k3 = Key.A | Key.C; // I want a

如果枚举中只有3个值,那么最快和最简单的方法可能是逐个检查它们。但是,对于一般解决方案,您可能希望尝试将
k1
的值转换为整数,找到将其除以的最大2次方,然后将其转换回Keys enum值

  • 获取中所有值的列表 枚举
  • 将这些值映射到某种类型的 可比数据类型
  • 比较所有的值并保持一致 最低的轨道
  • 将最低的转换回最低的 枚举类型
  • Keys key=Keys.b | Keys.c;
    var lower=Enum.GetValues(typeof(Keys))
    第()类
    .其中(x=>(x&键)!=0)
    .OrderBy(x=>x)
    .DefaultIfEmpty((键)0);
    控制台写入线(最低);
    
    您可以使用一些技巧:

    Key key = Key.B | Key.C;
    Key lowest = (Key)((int)key & -(int)key);
    

    需要是一个迭代实现,在其中测试位。我会这样做

    unsigned int k = (unsigned int) k1;
    int pos = -1;
    while (k) {
       pos++;
       if (k & 0x1) break;
       k >>= 1;
    }
    Keys lowestKey = 0;
    if (pos >= 0) lowestKey = 0x1 << pos;
    
    unsigned int k=(unsigned int)k1;
    int pos=-1;
    while(k){
    pos++;
    如果(k&0x1)中断;
    k>>=1;
    }
    Keys lowerstkey=0;
    
    如果(pos>=0)lowestKey=0x1您最初发布的代码没有意义:a+b+c没有类型名前缀,因此它们不会引用它们似乎要引用的枚举名

    此外,如果使用按位AND组合标志,结果将在所有参数中包含所有打开的标志-在本例中为“无”。

    Keys key=Keys.b | Keys.c;
    
    Keys key = Keys.b | Keys.c;
    
    var lowest = Enum.GetValues(typeof(Keys))
        .Cast<Keys>()
        .OrderBy(x => x)
        .FirstOrDefault(x => key.HasFlag(x));
    
    var lower=Enum.GetValues(typeof(Keys)) .Cast() .OrderBy(x=>x) .FirstOrDefault(x=>key.HasFlag(x));

    LINQ方法的.NET 4.0-ish版本稍微更有效。

    这是你的家庭作业,不是吗?另外,如果这是按位枚举,它需要一个Flags属性,通常一个None值=0,而你在构建集合时不需要按位和按位标记,你或他们。@Gjorgji和@NickLarsen:我刚刚意识到并解决了这个问题,除非应用了Flags属性,否则就没有意义了。@David:我个人认为它几乎不可读。这是一个有趣的奇怪现象,但我希望没有人真的在生产代码中使用它!我更喜欢使用LINQ方法之一。如果有人真的用这个,我希望他们至少在评论中解释一下它在做什么。是的,这需要一点时间,但我可以向你保证它是最快的,而且非常简洁。这当然是可读性和效率的折衷。话虽如此,我可能会把这样的东西放进去,然后忘记我后来做了什么。不过,如果你只是简单地谈论极客因素,那就很酷了。我想你应该在第一个之前添加类似
    .DefaultIfEmpty((Keys)0)
    的内容,这样当key为0时就不会抛出异常。
    Keys key = Keys.b | Keys.c;
    
    var lowest = Enum.GetValues(typeof(Keys))
        .Cast<Keys>()
        .OrderBy(x => x)
        .FirstOrDefault(x => key.HasFlag(x));