C# 如何将枚举标志与字典键进行比较?

C# 如何将枚举标志与字典键进行比较?,c#,dictionary,enums,C#,Dictionary,Enums,我有这个枚举标志: [Flags()] public enum Levels { Beginner, Medium, Advanced, Master } 我有一个叫做Bank的属性,这是一个字典,你可以选择级别 让我们假设我的第一个KeyValuePair包含以下Key=Levels.初学者| Levels.Medium | Levels。高级。因此,如果我在字典Levels.Medium中输入,则会返回最后一个对象,因为Medium是一个可能的值 public Worksheet

我有这个枚举标志:

[Flags()]
public enum Levels
{
    Beginner, Medium, Advanced, Master
}
我有一个叫做Bank的属性,这是一个
字典
,你可以选择级别

让我们假设我的第一个
KeyValuePair
包含以下
Key=Levels.初学者| Levels.Medium | Levels。高级
。因此,如果我在字典
Levels.Medium
中输入,则会返回最后一个对象,因为Medium是一个可能的值

public Worksheet LoadWorksheet(Levels level)
{
    Worksheet worksheet = new Worksheet(this.Bank[level].Value, this.Bank[level].Key);
    return worksheet;
}

但不幸的是,当我这样做时,抛出一个错误,指出密钥不存在。如何匹配键?

以2的幂定义枚举常量,即1、2、4、8等。这意味着组合枚举常量中的各个标志不重叠:

[Flags]
public enum Levels
{
    Beginner = 1, 
    Medium = 2,
    Advanced = 4, 
    Master = 8
}
并且必须将字典键定义为整数:
字典
。并在添加到字典时强制转换为
int

Bank.Add((int) (Levels.Medium|Levels.Master), ...);
然后将键与枚举标志进行比较:

if ((this.Bank[level].Key & Levels.Advanced) == Levels.Advanced)
{
     // Do something
}
如果使用.NET4,则使用HasFlag

if ( this.Bank[level].Key.HasFlag(Levels.Advanced) )
{
     // Do something
}

注意


字典。键必须是唯一的。当尝试添加重复键时,else会抛出一个
ArgumentException
。因此,不建议对
Dictionary.Key
使用标志枚举。试着把一些放在别的地方。

首先,我应该指出,如果:

Levels keyA = Levels.Beginner | Levels.Medium | Levels. Advanced;
Levels keyB = Levels.Medium;
然后:

在字典中查找值时,字典首先使用键的哈希值来确定正确的bucket,然后使用相等比较来标识bucket中正确的键

如果散列值不相等,则找不到密钥。如果键值不相等,则找不到该值

通过使用以下LINQ表达式查看键中是否存在其位模式,可以获取包含
Levels.Medium
的键的所有条目:

var mediumEntries = Bank.Where(entry => 0 != ((int)entry.Key & (int)Levels.Medium));
或者,正如@Ria所指出的,在.Net 4中,您可以使用HasFlags成员:

var mediumEntries = Bank.Where(entry => entry.Key.HasFlag(Levels.Medium));
另一个答案(@dasblinkenlight,@Ria)提出了一个好的观点,即枚举的值需要具有非重叠位模式才能工作:

[Flags()]        
public enum Levels        
{        
    Beginner = 0x01, 
    Medium = 0x02, 
    Advanced = 0x04, 
    Master = 0x08
}   

我理解,但在这种情况下,我如何处理这个问题?在本例中,keyB在a中包含一个值,因此我尝试匹配该值。。但是我没有idea@DarfZon我在想一个样品。KeyValuePair值的类型是什么?它是一个列表,其中T是一个自定义类,我只是想添加它,因为您不再直接按键查找值,而是使用LINQ表达式在
字典中搜索,就像它是一个
IEnumerable
,您基本上错过了
字典
的大部分性能改进。您没有使用内部哈希表的快速查找。为什么键类型必须是
int
?这是否意味着OP必须始终将键值强制转换回枚举类型?我认为在执行逐位操作时,最好将枚举值强制转换为int。
[Flags()]        
public enum Levels        
{        
    Beginner = 0x01, 
    Medium = 0x02, 
    Advanced = 0x04, 
    Master = 0x08
}