如何在忽略大小写的情况下测试是否定义了枚举?

时间:2010-07-01 12:52:41

标签: c# enums case-sensitive

以下通用静态方法采用字符串并返回枚举

很好忽略大小写,因为我将ignoreCase参数设置为true。

但是,我还想测试枚举是否存在,但执行此操作的enum.IsDefined方法似乎没有 ignoreCase 参数。

如何测试是否定义了枚举并且同时忽略了这种情况?

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

10 个答案:

答案 0 :(得分:36)

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

答案 1 :(得分:29)

除了@ Darin的回答,在.NET 4.0中,Enum类型现在有一个TryParse方法:

MyEnum result;
Enum.TryParse("bar", true, out result);

要记住的重要一点是,Parse与TryParse的行为存在根本区别。解析方法会抛出异常。 TryParse方法不会。了解您是否可能尝试解析许多项目非常重要。

答案 2 :(得分:5)

改为使用Enum.TryParse

T val;

if(Enum.TryParse(text, true, out val))
    return val;
else 
    return default(T);

答案 3 :(得分:5)

我正在使用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;
}

HTH

答案 4 :(得分:5)

正如其他人所说的那样,你可以简单地使用Enum.TryParse

但是,如果您想要一个更强大/一般的转换,允许您转换的不仅仅是字符串,那么您还需要使用Enum.IsDefined,不幸的是,正如您所发现的那样,不是不区分大小写。

Enum.TryParse (可以)不区分大小写。但不幸的是,它允许超出范围的整数通过!

所以解决方案是将它们一起使用(顺序很重要)。

我写了一个扩展方法就是这么做的。它允许从string,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,因为我有“重载”,它将不同的类型作为主要输入(见上文),但您可以使用{{1}类型的变量执行此操作如果这就是你想要的那么就好了(显然将string改为value.ToString())。

value

我的扩展方法还有很多......它允许你指定默认值,处理超出范围的int就好了,并且完全不区分大小写。如果有人感兴趣,我可以发布更多内容。

答案 5 :(得分:1)

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

使文本与枚举字符串相同:

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

答案 8 :(得分:0)

我有一个类似的问题,并使用public class GenericControllerFeatureProvider : IApplicationFeatureProvider<ControllerFeature> { public void PopulateFeature(IEnumerable<ApplicationPart> parts, ControllerFeature feature) { // This is designed to run after the default ControllerTypeProvider, // so the list of 'real' controllers has already been populated. foreach (var entityType in EntityTypes.Types) { var typeName = entityType.Name + "Controller"; if (!feature.Controllers.Any(t => t.Name == typeName)) { // There's no 'real' controller for this entity, so add the generic version. var controllerType = typeof(GenericController<>) .MakeGenericType(entityType.AsType()).GetTypeInfo(); feature.Controllers.Add(controllerType); } } } } (不区分大小写的标记设置为.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

在这里,我创建了一个.NET Fiddle,清楚地证明了这一点。

答案 9 :(得分:0)

首先使用Enum.TryParse方法获取类型为T的对象,然后将该对象传递给Enum.IsDefined方法:

private static T ConvertStringToEnum<T>(string stringValue) where T : struct
{
    if (System.Enum.TryParse(stringValue, out T result))
    {
        if (System.Enum.IsDefined(typeof(T), result) || result.ToString().Contains(","))
            return result;

        throw new System.Exception($"{stringValue} is not an underlying value of the {typeof(T).FullName} enumeration.");
    }

    throw new System.Exception($"{stringValue} is not a member of the {typeof(T).FullName} enumeration.");
}