3

我有这个枚举标志:

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

我有一个名为 Bank 的属性,它是 aDictionary<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;
}

但不幸的是,当我这样做时,会抛出一个错误,指出密钥不存在。我该怎么做才能匹配密钥?

4

2 回答 2

2

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

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

然后:

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

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

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

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

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
}   
于 2012-07-15T05:12:00.447 回答
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必须是唯一的。elseArgumentException在尝试添加重复键时抛出。因此不建议对Dictionary.Key. 尝试在其他地方存储一些。

于 2012-07-15T05:10:57.933 回答