Ответ 1
public enum MyEnum
{
Bar,
Foo
}
class Program
{
static void Main(string[] args)
{
var containsFoo = Enum.GetNames(typeof(MyEnum)).Any(x => x.ToLower() == "foo");
Console.WriteLine(containsFoo);
}
}
Следующий общий статический метод принимает строку и возвращает перечисление.
Это красиво игнорирует регистр, поскольку я устанавливаю для параметра ignoreCase значение true.
Однако я также хочу проверить, существует ли перечисление, но метод enum.IsDefined для этого не имеет параметра ignoreCase. p >
Как я могу проверить, определено ли перечисление или нет, и в том же случае игнорировать?
using System;
namespace TestEnum2934234
{
class Program
{
static void Main(string[] args)
{
LessonStatus lessonStatus = StringHelpers.ConvertStringToEnum<LessonStatus>("prepared");
ReportStatus reportStatus = StringHelpers.ConvertStringToEnum<ReportStatus>("finished");
Console.WriteLine(lessonStatus.ToString());
Console.WriteLine(reportStatus.ToString());
Console.ReadLine();
}
}
public static class StringHelpers
{
public static T ConvertStringToEnum<T>(string text)
{
if (Enum.IsDefined(typeof(T), text)) //does not have ignoreCase parameter
return (T)Enum.Parse(typeof(T), text, true);
else
return default(T);
}
}
public enum LessonStatus
{
Defined,
Prepared,
Practiced,
Recorded
}
public enum ReportStatus
{
Draft,
Revising,
Finished
}
}
public enum MyEnum
{
Bar,
Foo
}
class Program
{
static void Main(string[] args)
{
var containsFoo = Enum.GetNames(typeof(MyEnum)).Any(x => x.ToLower() == "foo");
Console.WriteLine(containsFoo);
}
}
Наряду с ответом @Darin в .NET 4.0 тип Enum теперь имеет метод TryParse:
MyEnum result;
Enum.TryParse("bar", true, out result);
Важно помнить, что существует фундаментальное различие в поведении Parse vs TryParse. Методы анализа порождают исключения. Методы TryParse не будут. Это очень важно знать, если вы потенциально пытаетесь проанализировать многие элементы.
Я использую Compact Framework 3.5 и:
Enum.TryParse
... не существует. Он имеет:
Enum.IsDefined
.. но это не поддерживает параметр ignoreCase. Я бы хотел получить лучшее из обоих миров, поэтому придумал это (как вспомогательный метод)...
public bool TryParse<TEnum>(string value, bool ignoreCase, ref TEnum result) where TEnum : struct
{
bool parsed;
try
{
result = (TEnum)Enum.Parse(typeof(TEnum), value, ignoreCase);
parsed = true;
}
catch { }
return parsed;
}
НТН
Вместо этого используйте Enum.TryParse:
T val;
if(Enum.TryParse(text, true, out val))
return val;
else
return default(T);
Вы могли бы уйти просто с помощью Enum.TryParse
, как говорили другие.
Однако, если вы хотите более надежное/общее преобразование, которое позволяет вам конвертировать больше, чем просто строки, вам также нужно использовать Enum.IsDefined
, который, к сожалению, по вашему усмотрению, не не чувствителен к регистру.
Enum.TryParse
является (может быть) нечувствительным к регистру. Но, к сожалению, он позволяет выйти из дальнего зарубежья!
Итак, решение состоит в том, чтобы использовать их вместе (и порядок важен).
Я написал метод расширения, который делает именно это. Он позволяет конвертировать из строки, int/int? И любого другого Enum/Enum? типа типа:
string value1 = "Value1";
Enum2 enum2 = value1.ParseToEnum<Enum2>();
Debug.Assert(enum2.ToString() == value1);
Enum1 enum1 = Enum1.Value1;
enum2 = enum1.ParseToEnum<Enum2>();
Debug.Assert(enum2.ToString() == enum1.ToString());
int value2 = 1;
enum2 = value2.ParseToEnum<Enum2>();
Debug.Assert(enum2.GetHashCode() == value2);
Здесь сердце метода. Это часть преобразования, которая отвечает на ваш вопрос. Переменная value
имеет тип object
из-за "перегрузок", которые у меня есть, которые принимают разные типы в качестве основного входа (см. Выше), но вы можете сделать это с переменной типа string
просто отлично, если все вы хотите (явно меняя value.ToString()
на value
).
if (value != null)
{
TEnum result;
if (Enum.TryParse(value.ToString(), true, out result))
{
// since an out-of-range int can be cast to TEnum, double-check that result is valid
if (Enum.IsDefined(typeof(TEnum), result.ToString()))
{
return result;
}
}
}
В моем методе расширения гораздо больше возможностей... он позволяет вам указывать значения по умолчанию, обрабатывать вне диапазона ints просто отлично и полностью не учитывает регистр. Я могу опубликовать его больше, если кто-то заинтересован.
enum DaysCollection
{
sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
public bool isDefined(string[] arr,object obj)
{
bool result=false;
foreach (string enu in arr)
{
result = string.Compare(enu, obj.ToString(), true) == 0;
if (result)
break;
}
return result;
}
private void button1_Click(object sender, EventArgs e)
{
object obj = "wednesday";
string[] arr = Enum.GetNames(typeof(DaysCollection)).ToArray();
isDefined(arr,obj);
}
public static T ConvertStringToEnum<T>(string text)
{
T returnVal;
try
{
returnVal = (T) Enum.Parse( typeof(T), text, true );
}
catch( ArgumentException )
{
returnVal = default(T);
}
return returnVal;
}
Сделайте текст в том же случае, что и строка перечисления:
enum FileExts
{
jpg,
pdf
}
if (Enum.IsDefined(typeof(T), text.tolower())) //does not have ignoreCase parameter
return (T)Enum.Parse(typeof(T), text, true);
else
return default(T);
У меня была аналогичная проблема, и я использовал комбинацию как .Enum.TryPase
(с флагом, чувствительным к регистру, как true
) и Enum.IsDefined
. В качестве упрощения для вашего вспомогательного класса рассмотрите следующее:
public static class StringHelpers
{
public static T ConvertStringToEnum<T>(string text)
{
T result;
return Enum.TryParse(text, true, out result)
&& Enum.IsDefined(result.ToString())
? result
: default(T);
}
}
И пока мы на нем, так как класс-помощник статичен, а метод статичен, мы можем сделать это методом расширения на string
.
public static class StringExtensions
{
public static TEnum ToEnum<TEnum>(this string text)
where TEnum : struct, IComparable, IFormattable, IConvertible
{
TEnum result = default(TEnum);
return !string.IsNullOrWhiteSpace(text)
&& Enum.TryParse(text, true, out result)
&& Enum.IsDefined(typeof(TEnum), result.ToString())
? result
: default(TEnum);
}
}
Здесь я создал .NET Fiddle
, который наглядно демонстрирует это.