1

I have a scenario like the following, I have an enum, I get some text which is parsed to create a list of enums which I want to pass into ReportResults which will create an email based on the flags passed in. I don't have access to change the enum or the ReportResults method, is there a way to pass in something like the resultFlags variable? Is there a way to use an Enum.TryParse to create a single item to pass in? (there must be times where serialization requires something like this)

    [Flags]
    public enum Result
    {
        None = 0,
        Warning = 2,
        Error = 4,
        Success = 8,
        Failure = 16
    }

    public void ProcessResultValues(string log)
    {
        var resultFlags = new List<Result>();

        /// Process log text, add Result flags to the resultFlags list

        ReportResults(resultFlags);
    }

    public void ReportResults(Result results)
    {
        /// Based on the flags, generate a text to describe if the process succeeded or failed and if there were any warnings or errors encountered during processing.
    }
ScottFoster1000
  • 577
  • 1
  • 10
  • 25
  • 1
    Possible duplicate of [What does the \[Flags\] Enum Attribute mean in C#?](https://stackoverflow.com/questions/8447/what-does-the-flags-enum-attribute-mean-in-c) – Matt.G Nov 06 '19 at 21:16
  • 3
    A bit odd to have a flag that could be both `results & Result.Success` and `results & Result.Failure`. – Jonathon Chase Nov 06 '19 at 21:18
  • Well, it's just an example, but you could have something where a process completes successfully even if it had warnings. – ScottFoster1000 Nov 07 '19 at 00:35

2 Answers2

12

Since Result is set up correctly as a bit flags enum (which means the one enum variable can hold several enum values), you can just or them together to get a single combined enum to pass around. The easiest way to do that would be using the Enumerable. Aggregate method

Applies an accumulator function over a sequence.

var result = resultFlags.Aggregate((x, y) => x |= y);

It's the same as combining them manually, eg

Days meetingDays = Days.Tuesday | Days.Thursday;

The reason why bit flags work, is the way the numbers are laid out, each value is not mutually exclusive and can be packed and unpacked in binary easily using bitwise operations (hence the name bit flags). They have been around for ever.


Further Reading

Enumeration types as bit flags

You can use an enumeration type to define bit flags, which enables an instance of the enumeration type to store any combination of the values that are defined in the enumerator list

You create a bit flags enum by applying the System.FlagsAttribute attribute and defining the values appropriately so that AND, OR, NOT and XOR bitwise operations can be performed on them. In a bit flags enum, include a named constant with a value of zero that means "no flags are set."

halfer
  • 19,824
  • 17
  • 99
  • 186
TheGeneral
  • 79,002
  • 9
  • 103
  • 141
1

You can try this but the None value should be 1 because if 0 the flag will be always on.

[Flags]
public enum Result
{
  None = 1,
  Warning = 2,
  Error = 4,
  Success = 8,
  Failure = 16
}

public void ProcessResultValues(string log)
{
  var resultFlags = new List<Result>();

  // For test
  resultFlags.Add(Result.Warning);
  resultFlags.Add(Result.Success);

  Result results = default(Result);
  resultFlags.ForEach(value => results |= value);

  ReportResults(results);
}

public void ReportResults(Result results)
{
  // For test
  foreach ( Enum value in Enum.GetValues(typeof(Result)) )
    if ( results.HasFlag(value) )
      Console.WriteLine(value);
}

Output

Warning
Success

If None is 0:

None
Warning
Success
  • Thanks for the response Olivier, I actually used your code, but it seems it's essentially the same as The General's so I selected his as the answer since it was submitted a few minutes earlier. – ScottFoster1000 Nov 12 '19 at 00:29