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

时间:2012-07-15 05:00:56

标签: c# dictionary enums

我有这个枚举标志:

[Flags()]
public enum Levels
{
    Beginner, Medium, Advanced, Master
}

我有一个名为Bank的属性,这是一个Dictionary<Levels, ...>,Levels是您可以选择的可能选项

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

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

但不幸的是,当我这样做时,会向我发出错误,指出密钥不存在。如何匹配密钥呢?

2 个答案:

答案 0 :(得分:2)

首先,我应该指出:if:

Levels keyA = Levels.Beginner | Levels.Medium | Levels. Advanced;
Levels keyB = Levels.Medium;

然后:

Debug.Assert(keyA.GetHashCode() != keyB.GetHashCode());
Debug.Assert(keyA != keyB);

在字典中查找值时,字典首先使用密钥的哈希值来确定正确的存储桶,然后使用相等比较来识别存储桶中的正确密钥。

如果哈希值不相等,则找不到密钥。如果键值不相等,则不会找到该值。

您可以通过查看具有以下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
}   

答案 1 :(得分:0)

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

[Flags]
public enum Levels
{
    Beginner = 1, 
    Medium = 2,
    Advanced = 4, 
    Master = 8
}

并且必须将Dictionary Key定义为Integer:Dictionary<int, ...>。并在添加到词典时转换为int

Bank.Add((int) (Levels.Medium|Levels.Master), ...);

然后将Key与枚举标志进行比较:

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

如果使用.NET4,请使用HasFlag

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

注意

Dictionary.Key必须是唯一的。尝试添加重复键时,else会抛出ArgumentException。这样就不会为Dictionary.Key建议使用Flag枚举。尝试将其他地方存储在其他地方。