Enum.Parse не может привести строку - PullRequest
5 голосов
/ 23 ноября 2011

Я пытаюсь загрузить некоторые AppSettings в объект. Настройки выглядят так:

<?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>

Logging_levels представляет несколько значений перечисления, которые разрешены настройками. Я пытаюсь загрузить их в свой объект, используя следующий код:

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

Но это не работает, и я получаю только LogLevel.Info, а не значение Loglevel.Error | LogLevel.Warning | LogLevel.Info. Перечисление определяется следующим образом:

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

Я ошибаюсь, определяя значения в шестнадцатеричном формате? или я что-то пропустил?

Ответы [ 4 ]

4 голосов
/ 23 ноября 2011

Ваши enum значения будут вызывать проблемы.

Значения Flags enum должны быть степенью двойки, и вы не должны использовать 0 для каких-либо значений, кроме какого-либо индикатора пустых / нет / ничего.

Имеет ли это какое-то значение?

[Flags]
public enum LogLevel
{
    None        =  0
    Error       =  1,
    Warning     =  2,
    Info        =  4,
    Debug       =  8,
    Performance = 16
}
4 голосов
/ 23 ноября 2011

Могут помочь правильные значения флага (каждое значение должно устанавливать свой бит):

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

Примечание: вы можете удалить «Нет», если хотите.

3 голосов
/ 23 ноября 2011

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

Параметр value содержит строковое представление базового значения или именованной константы члена перечисления или список именованных констант, разделенных запятыми (,).Один или несколько пробелов могут предшествовать или следовать за каждым значением, именем или запятой в значении.Если значение является списком, возвращаемое значение является значением указанных имен в сочетании с побитовой операцией ИЛИ.

Так что это должно работать, и ik выглядит так:

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");
}

Дает мне "Ошибка" и "Предупреждение".Однако при проверке переменной level в Visual Studio отображается только «Предупреждение».Возможно, это вас оттолкнуло.; -)


Edit: @svick и @ jv42 правы, это неверные значения вашего флага.

2 голосов
/ 23 ноября 2011

Проблема не в разборе!Проблема в преобразовании в текст.Поскольку значения флага не являются различными битовыми масками, нет детерминированного отображения на строку и обратно.Как уже упоминалось другими, вы должны выбрать такие значения, как, например:

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

См. MSDN: анализ значений перечисления

См. Демонстрационный пример: 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);
         }
      }
   }
}

Вывод:

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.

Примечание по производительности:

Если производительность важна, не полагаться на Enum.Parse :)

См. Как мне преобразовать строку в перечисление в C #?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...