5

I'm trying to load some AppSettings into an object. The settings look like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="Logging_default_path" value="C:\Temp" />
    <add key="Logging_max_file_size" value="10485760" />
    <add key="Logging_levels" value="Error,Warning,Info"/>
    <add key="Logging_filename" value="RobinsonLog" />
  </appSettings>
</configuration>

The Logging_levels represents several enum values that are allowed by the settings. I'm trying to load these into my object by using the following code:

Level = (LogLevel)Enum.Parse(typeof(LogLevel), settings["Logging_levels"]);

But this is not working and I'm only getting LogLevel.Info returned, not the value of Loglevel.Error | LogLevel.Warning | LogLevel.Info. The enum is defined as followed:

[Flags]
public enum LogLevel
{
    Error = 0x0,
    Warning = 0x1,
    Info = 0x2,
    Debug = 0x3,
    Performance = 0x4
}

Am I wrong by defining the values in hex? or did I miss something else?

2
  • Have you tried creating an enum with your expected value and converting this to string? This should show the proper syntax. Commented Nov 23, 2011 at 13:26
  • 2
    Your flags values are wrong. The way it's written Warning | Info == Debug and Debug == Debug | Error. Commented Nov 23, 2011 at 13:28

4 Answers 4

4

Your enum values are going to cause problems.

The values of a Flags enum must be powers of two, and you shouldn't use 0 for any value other than some kind of empty/none/nothing indicator.

Does this make any difference?

[Flags]
public enum LogLevel
{
    None        =  0
    Error       =  1,
    Warning     =  2,
    Info        =  4,
    Debug       =  8,
    Performance = 16
}
Sign up to request clarification or add additional context in comments.

4 Comments

This did the trick. Seems the hex values are indeed not appreciated by the parser.
Technically, they don't have to be powers of two. For example, [Flags] enum FooBar { Foo = 5, Bar = 10 } would work correctly too. But doing that would be completely unnecessary complication. There is no reason not to use powers of two.
@NekoNova, it's not about using hex or decimal. It's about specifying the correct values.
@NekoNova: It's nothing to do with whether or not the value literals are written in hex. The values must be powers of two. It will work exacly the same if you declare them as 0x00, 0x01, 0x02, 0x04, 0x08, and 0x10.
4

Proper flag values might help (each value should set a different bit):

[Flags]
public enum LogLevel
{
    None = 0x0,
    Error = 0x1,
    Warning = 0x2,
    Info = 0x4,
    Debug = 0x8,
    Performance = 0x10
}

Note: you can remove the 'None' if you wish.

Comments

3

http://msdn.microsoft.com/en-us/library/essfb559.aspx

The value parameter contains the string representation of an enumeration member's underlying value or named constant, or a list of named constants delimited by commas (,). One or more blank spaces can precede or follow each value, name, or comma in value. If value is a list, the return value is the value of the specified names combined with a bitwise OR operation.

So it should work, and ik looks like it does:

LogLevel level = (LogLevel)Enum.Parse(typeof(LogLevel), "Error,Warning");

if ((level & LogLevel.Error) == LogLevel.Error)
{
    Console.WriteLine("Error");
}

if ((level & LogLevel.Warning) == LogLevel.Warning)
{
    Console.WriteLine("Warning");
}

if ((level & LogLevel.Info) == LogLevel.Info)
{
    Console.WriteLine("Info");
}

Gives me "Error" and "Warning". However, by inspecting the level variable in Visual Studio, it only shows "Warning". Perhaps that set you off. ;-)


Edit: @svick and @jv42 are right, it are your flag values that are wrong.

1 Comment

debug reports correct value. it's the incorrect value of the flags that causes the problem
2

The problem isn't the parsing! The problem is the conversion to text, instead. Because the flag values aren't distinct bit masks, there is no deterministic mapping to string and back. As mentioned by others, you should choose the values like e.g.:

[Flags]
public enum LogLevel
{
    None = 0
    Error = 1 << 0,
    Warning = 1 << 1,
    Info = 1 << 2,
    // etc
}

See MSDN: Parsing Enumeration Values

See a demo live: https://ideone.com/8AkSQ

using System;

[Flags] enum Colors { None=0, Red = 1, Green = 2, Blue = 4 };

public class Example
{
   public static void Main()
   {
      string[] colorStrings = { "0", "2", "8", "blue", "Blue", "Yellow", "Red, Green" };
      foreach (string colorString in colorStrings)
      {
         try {
            Colors colorValue = (Colors) Enum.Parse(typeof(Colors), colorString);        
            if (Enum.IsDefined(typeof(Colors), colorValue) | colorValue.ToString().Contains(","))  
               Console.WriteLine("Converted '{0}' to {1}.", colorString, colorValue.ToString());
            else
               Console.WriteLine("{0} is not an underlying value of the Colors enumeration.", colorString);
         }
         catch (ArgumentException) {
            Console.WriteLine("'{0}' is not a member of the Colors enumeration.", colorString);
         }
      }
   }
}

Output:

Converted '0' to None.
Converted '2' to Green.
8 is not an underlying value of the Colors enumeration.
'blue' is not a member of the Colors enumeration.
Converted 'Blue' to Blue.
'Yellow' is not a member of the Colors enumeration.
Converted 'Red, Green' to Red, Green.

Performance Note:

If performance is important, do not rely on Enum.Parse :)

See How should I convert a string to an enum in C#?

6 Comments

According to the doc, parsing flags is supported at least since .Net 2.0.
Read that article, and I have the flags attribute, but it does not explain how to parse a string into a collection of flags
The sample says: Converted 'Red, Green' to Red, Green. Do you want to get a collection of flags from the combined value? That has zero to do with parsing
your code does not perform what I intended. I can parse single values without problems, its the combination of values that cuases the problem
@NekoNova: ah, the flags values should be non-overlapping to do what you expect too, as mentioned by other, notably svick!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.