简体   繁体   English

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

[英]How to compare an enum flag to a Dictionary key?

I've got this enum flag: 我有这个枚举标志:

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

I've got a property called Bank, where this is a Dictionary<Levels, ...> and Levels are the possible options that you can choose 我有一个名为Bank的属性,这是一个Dictionary<Levels, ...>和Levels是你可以选择的选项

Let's go to suppose that my first KeyValuePair contains the following Key = Levels.Beginner | Levels.Medium | Levels. Advanced 让我们假设我的第一个KeyValuePair包含以下Key = Levels.Beginner | Levels.Medium | Levels. Advanced Key = Levels.Beginner | Levels.Medium | Levels. Advanced Key = Levels.Beginner | Levels.Medium | Levels. Advanced . Key = Levels.Beginner | Levels.Medium | Levels. Advanced So the idea if I enter in the dictionary Levels.Medium , returns me the last object because Medium is a possible value. 因此,如果我输入字典Levels.Medium ,我会返回最后一个对象,因为Medium是一个可能的值。

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

But unfortunatly, when I do this, throws me an error pointing that the key does not exist. 但不幸的是,当我这样做时,抛出一个错误,指出密钥不存在。 How can I do to match the key? 我该怎么做才能匹配钥匙?

First, I should point out that if: 首先,我应该指出:

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

then: 然后:

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

When looking up values in the dictionary, the dictionary first uses the hash value of the key to determine the correct bucket, and then uses equality comparison to identify the right key in the bucket. 在字典中查找值时,字典首先使用密钥的哈希值来确定正确的存储桶,然后使用相等比较来识别存储桶中的正确密钥。

If the hash values are not equal then the key will not be found. 如果哈希值不相等,则将找不到密钥。 If the key values are not equal, then the value will not be found. 如果键值不相等,则不会找到该值。

You can get all entries that have a key containing Levels.Medium by seeing if it's bit pattern is present in the key with the following LINQ expression: 您可以通过查看具有以下LINQ表达式的键中是否存在位模式来获取具有包含Levels.Medium的键的所有条目:

var mediumEntries = Bank.Where(entry => 0 != ((int)entry.Key & (int)Levels.Medium));

Or, as @Ria pointed out, in .Net 4 you can use the HasFlags member: 或者,正如@Ria指出的那样,在.Net 4中你可以使用HasFlags成员:

var mediumEntries = Bank.Where(entry => entry.Key.HasFlag(Levels.Medium));

The good point was made in another answers (@dasblinkenlight, @Ria) that the values of your enumeration need to have non-overlapping bit patterns for this to work: 在另一个答案(@dbblinkenlight,@ Ria)中提出了一个好处,即枚举的值需要具有非重叠的位模式才能使其工作:

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

Define enumeration constants in powers of two, that is, 1, 2, 4, 8, and so on. 定义2的幂的枚举常量,即1,2,4,8等。 This means the individual flags in combined enumeration constants do not overlap: 这意味着组合枚举常量中的各个标志不重叠:

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

and you must define Dictionary Key as Integer: Dictionary<int, ...> . 你必须将Dictionary Key定义为Integer: Dictionary<int, ...> and cast to int when adding to dictionary: 并在添加到字典时转换为int

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

then compare Key to enum flags: 然后将Key与枚举标志进行比较:

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

and if using .NET4 use HasFlag 如果使用.NET4,请使用HasFlag

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

Note : 注意

Dictionary.Key must be unique. Dictionary.Key必须是唯一的。 else throws an ArgumentException when attempting to add a duplicate key. 尝试添加重复键时,else会抛出ArgumentException so that Flag enumeration is not suggested for Dictionary.Key . 因此不建议对Dictionary.Key Flag枚举。 Try to store some where else. 尝试在其他地方存储一些。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM