5

i'be looked some same topics but havn't find what i'm looking for I should use flag enum flag atribute and check if my data is in one of the collections of this enum For example, enum:

[Flags]
private enum MyEnum {
Apple,
Orange,
Tomato,
Potato
Melon,
Watermelon,

Fruit = Apple | Orange,
Vegetable = Tomato | Potato,
Berry = Melon | Watermelon,
}

In the method i should check a input data. How can i do it?

private void Checking(string data){
if(MyEnum.Fruit contains data) MessageBox.Show("Fruit");
if(MyEnum.Vegetable contains data) MessageBox.Show("Vegetables");
if(MyEnum.Berry contains data) MessageBox.Show("Berry");
}

What should be instead of "contains data"?

UPDATE

private void ZZZ(){
Cheching("Apple");
}
4

4 回答 4

11

First of, you need to manually number your values with the powers-of-2 sequence :

[Flags]
private enum MyEnum 
{
  None = 0,   // often useful
  Apple = 1,
  Orange = 2,
  Tomato = 4,
  Potato = 8,
  Melon =  16,
  Watermelon = 32,

  Fruit = Apple | Orange,
  Vegetable = Tomato | Potato,
  Berry = Melon | Watermelon,
}

The [Flags] attribute is not strictly necessary, it only controls the ToString() behaviour.

And to check whether a string matches your value you'll have to make it an enum first:

private void Checking(string data)
{      
    MyEnum v = (MyEnum) Enum.Parse(typeof(MyEnum), data);

    if((MyEnum.Fruit & v) != 0) MessageBox.Show("It's a Fruit"); 
    ...
}

But do note that interchanging between Enum and string like this with Parse() is limited.

于 2013-08-19T10:01:05.207 回答
2

In addition to Henk Holterman's solution you may use extension methods:

[Flags]
private enum MyEnum {
  None = 0, 
  Apple = 1,
  Orange = 2,
  Tomato = 4,
  Potato = 8,
  Melon = 16,
  Watermelon = 32,

  Berry = Melon | Watermelon, 
  Fruit = Apple | Orange,
  Vegetable = Potato | Tomato
}

private static class MyEnumExtensions { 
  public static Boolean IsFruit(this MyEnum value) {
    return (value & MyEnum.Fruit) == MyEnum.Fruit;
  }

  public static Boolean IsVegetable(this MyEnum value) {
    return (value & MyEnum.Vegetable) == MyEnum.Vegetable;
  }

  public static Boolean IsBerry(this MyEnum value) {
    return (value & MyEnum.Berry) == MyEnum.Berry;
  }
}

...

MyEnum data = ...

if (data.IsBerry()) {
  MessageBox.Show("Berry");       
} 
于 2013-08-19T10:06:30.580 回答
2

You also can use the HasFlag-method of the Enum-class. As Henk pointed out will need to assign the values to your enum manually using values of the powers-of-2 sequence.

[Flags]
private enum MyEnum 
{
    Apple = 1,
    Orange = 2,
    Tomato = 4,
    Potato = 8,
    Melon  16,
    Watermelon = 32,

    Fruit = Apple | Orange,
    Vegetable = Tomato | Potato,
    Berry = Melon | Watermelon,
}

Then, to check you could use the following method which is working for all composed parts of your enumeration:

void Cheking(string data)
{
    // Get the enum value of the string passed to the method
    MyEnum myEnumData;
    if (Enum.TryParse<MyEnum>(data, out myEnumData))
    {
        // If the string was a valid enum value iterate over all the value of
        // the underlying enum type
        var values = Enum.GetValues(typeof(MyEnum)).OfType<MyEnum>();
        foreach (var value in values)
        {
            // If the value is not a power of 2 it is a composed one. If it furthermore
            // has the flag passed to the method this is one we searched.
            var isPowerOfTwo = (value != 0) && ((value & (value - 1)) == 0);
            if (!isPowerOfTwo && value.HasFlag(myEnumData))
            {
                MessageBox.Show(value.ToString());
            }
        }
    }
    // In case an invalid value had been passed to the method
    // display an error message.
    else
    {
        MessageBox.Show("Invalid Value");
    }
}

Or to write it in a shorter way using LINQ:

var results = Enum.GetValues(typeof(MyEnum))
                  .OfType<MyEnum>()
                  .Select(x => new { Value = x, IsPowerOfTwo = (x != 0) && ((x & (x - 1)) == 0) } )
                  .Where(x => !x.IsPowerOfTwo && x.Value.HasFlag(myEnumData))
                  .Select(x => x.Value.ToString());

This will give an IEnumerable<string> containing the results. In case that myEnumData has a value of MyEnum.Apple the result will contain just the value "Fruit".

于 2013-08-19T10:09:51.187 回答
1

as @Henk Holterman has suggested, you need first to assign values to the enum.
All values should be a power of 2 (and avoid using 0, except for the special case of "None") It should look something like this:

 MyEnum eVal= (MyEnum ) Enum.Parse( typeof(MyEnum), data, true );
 if((MyEnum.Fruit & eVal) != 0) MessageBox.Show("Fruit");

You might want to read more about bitwise and boolean algebra.

于 2013-08-19T10:00:33.930 回答