如何为Enum值TryParse?

时间:2023-01-26 14:29:03

I want to write a function which can validate a given value (passed as a string) against possible values of an enum. In the case of a match, it should return the enum instance; otherwise, it should return a default value.

我想编写一个函数,它可以验证给定值(作为字符串传递)与枚举的可能值。在匹配的情况下,它应该返回枚举实例;否则,它应该返回一个默认值。

The function may not internally use try/catch, which excludes using Enum.Parse, which throws an exception when given an invalid argument.

该函数可能在内部不使用try / catch,它排除了使用Enum.Parse,它在给定无效参数时抛出异常。

I'd like to use something along the lines of a TryParse function to implement this:

我想使用TryParse函数的一些东西来实现这个:

public static TEnum ToEnum<TEnum>(this string strEnumValue, TEnum defaultValue)
{
   object enumValue;
   if (!TryParse (typeof (TEnum), strEnumValue, out enumValue))
   {
       return defaultValue;
   }
   return (TEnum) enumValue;
}

14 个解决方案

#1


As others have said, you have to implement your own TryParse. Simon Mourier is providing a full implementation which takes care of everything.

正如其他人所说,你必须实现自己的TryParse。 Simon Mourier正在提供一个完整的实现,它可以处理所有事情。

If you are using bitfield enums (i.e. flags), you also have to handle a string like "MyEnum.Val1|MyEnum.Val2" which is a combination of two enum values. If you just call Enum.IsDefined with this string, it will return false, even though Enum.Parse handles it correctly.

如果您正在使用位域枚举(即标志),您还必须处理像“MyEnum.Val1 | MyEnum.Val2”这样的字符串,它是两个枚举值的组合。如果你只是用这个字符串调用Enum.IsDefined,它将返回false,即使Enum.Parse正确处理它。

Update

As mentioned by Lisa and Christian in the comments, Enum.TryParse is now available for C# in .NET4 and up.

MSDN Docs

正如Lisa和Christian在评论中所提到的,Enum.TryParse现在可用于.NET4及更高版本的C#。 MSDN文档

#2


Enum.IsDefined will get things done. It may not be as efficient as a TryParse would probably be, but it will work without exception handling.

Enum.IsDefined将完成任务。它可能不如TryParse那样有效,但它可以在没有异常处理的情况下工作。

public static TEnum ToEnum<TEnum>(this string strEnumValue, TEnum defaultValue)
{
    if (!Enum.IsDefined(typeof(TEnum), strEnumValue))
        return defaultValue;

    return (TEnum)Enum.Parse(typeof(TEnum), strEnumValue);
}

Worth noting: a TryParse method was added in .NET 4.0.

值得注意的是:.NET 4.0中添加了TryParse方法。

#3


Here is a custom implementation of EnumTryParse. Unlike other common implementations, it also supports enum marked with the Flags attribute.

这是EnumTryParse的自定义实现。与其他常见实现不同,它还支持使用Flags属性标记的枚举。

    /// <summary>
    /// Converts the string representation of an enum to its Enum equivalent value. A return value indicates whether the operation succeeded.
    /// This method does not rely on Enum.Parse and therefore will never raise any first or second chance exception.
    /// </summary>
    /// <param name="type">The enum target type. May not be null.</param>
    /// <param name="input">The input text. May be null.</param>
    /// <param name="value">When this method returns, contains Enum equivalent value to the enum contained in input, if the conversion succeeded.</param>
    /// <returns>
    /// true if s was converted successfully; otherwise, false.
    /// </returns>
    public static bool EnumTryParse(Type type, string input, out object value)
    {
        if (type == null)
            throw new ArgumentNullException("type");

        if (!type.IsEnum)
            throw new ArgumentException(null, "type");

        if (input == null)
        {
            value = Activator.CreateInstance(type);
            return false;
        }

        input = input.Trim();
        if (input.Length == 0)
        {
            value = Activator.CreateInstance(type);
            return false;
        }

        string[] names = Enum.GetNames(type);
        if (names.Length == 0)
        {
            value = Activator.CreateInstance(type);
            return false;
        }

        Type underlyingType = Enum.GetUnderlyingType(type);
        Array values = Enum.GetValues(type);
        // some enums like System.CodeDom.MemberAttributes *are* flags but are not declared with Flags...
        if ((!type.IsDefined(typeof(FlagsAttribute), true)) && (input.IndexOfAny(_enumSeperators) < 0))
            return EnumToObject(type, underlyingType, names, values, input, out value);

        // multi value enum
        string[] tokens = input.Split(_enumSeperators, StringSplitOptions.RemoveEmptyEntries);
        if (tokens.Length == 0)
        {
            value = Activator.CreateInstance(type);
            return false;
        }

        ulong ul = 0;
        foreach (string tok in tokens)
        {
            string token = tok.Trim(); // NOTE: we don't consider empty tokens as errors
            if (token.Length == 0)
                continue;

            object tokenValue;
            if (!EnumToObject(type, underlyingType, names, values, token, out tokenValue))
            {
                value = Activator.CreateInstance(type);
                return false;
            }

            ulong tokenUl;
            switch (Convert.GetTypeCode(tokenValue))
            {
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.SByte:
                    tokenUl = (ulong)Convert.ToInt64(tokenValue, CultureInfo.InvariantCulture);
                    break;

                //case TypeCode.Byte:
                //case TypeCode.UInt16:
                //case TypeCode.UInt32:
                //case TypeCode.UInt64:
                default:
                    tokenUl = Convert.ToUInt64(tokenValue, CultureInfo.InvariantCulture);
                    break;
            }

            ul |= tokenUl;
        }
        value = Enum.ToObject(type, ul);
        return true;
    }

    private static char[] _enumSeperators = new char[] { ',', ';', '+', '|', ' ' };

    private static object EnumToObject(Type underlyingType, string input)
    {
        if (underlyingType == typeof(int))
        {
            int s;
            if (int.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(uint))
        {
            uint s;
            if (uint.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(ulong))
        {
            ulong s;
            if (ulong.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(long))
        {
            long s;
            if (long.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(short))
        {
            short s;
            if (short.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(ushort))
        {
            ushort s;
            if (ushort.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(byte))
        {
            byte s;
            if (byte.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(sbyte))
        {
            sbyte s;
            if (sbyte.TryParse(input, out s))
                return s;
        }

        return null;
    }

    private static bool EnumToObject(Type type, Type underlyingType, string[] names, Array values, string input, out object value)
    {
        for (int i = 0; i < names.Length; i++)
        {
            if (string.Compare(names[i], input, StringComparison.OrdinalIgnoreCase) == 0)
            {
                value = values.GetValue(i);
                return true;
            }
        }

        if ((char.IsDigit(input[0]) || (input[0] == '-')) || (input[0] == '+'))
        {
            object obj = EnumToObject(underlyingType, input);
            if (obj == null)
            {
                value = Activator.CreateInstance(type);
                return false;
            }
            value = obj;
            return true;
        }

        value = Activator.CreateInstance(type);
        return false;
    }

#4


In the end you have to implement this around Enum.GetNames:

最后,你必须围绕Enum.GetNames实现这个:

public bool TryParseEnum<T>(string str, bool caseSensitive, out T value) where T : struct {
    // Can't make this a type constraint...
    if (!typeof(T).IsEnum) {
        throw new ArgumentException("Type parameter must be an enum");
    }
    var names = Enum.GetNames(typeof(T));
    value = (Enum.GetValues(typeof(T)) as T[])[0];  // For want of a better default
    foreach (var name in names) {
        if (String.Equals(name, str, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase)) {
            value = (T)Enum.Parse(typeof(T), name);
            return true;
        }
    }
    return false;
}

Additional notes:

  • Enum.TryParse is included in .NET 4. See here http://msdn.microsoft.com/library/dd991876(VS.100).aspx
  • Enum.TryParse包含在.NET 4中。请参见http://msdn.microsoft.com/library/dd991876(VS.100).aspx

  • Another approach would be to directly wrap Enum.Parse catching the exception thrown when it fails. This could be faster when a match is found, but will likely to slower if not. Depending on the data you are processing this may or may not be a net improvement.
  • 另一种方法是直接包装Enum.Parse捕获失败时抛出的异常。找到匹配项时可能会更快,但如果没有,则可能会更慢。根据您正在处理的数据,这可能是也可能不是净改进。


EDIT: Just seen a better implementation on this, which caches the necessary information: http://damieng.com/blog/2010/10/17/enums-better-syntax-improved-performance-and-tryparse-in-net-3-5

编辑:刚刚看到一个更好的实现,它缓存了必要的信息:http://damieng.com/blog/2010/10/17/enums-better-syntax-improved-performance-and-tryparse-in-net- 3-5

#5


Based on .NET 4.5

基于.NET 4.5

Sample code below

示例代码如下

using System;

enum Importance
{
    None,
    Low,
    Medium,
    Critical
}

class Program
{
    static void Main()
    {
    // The input value.
    string value = "Medium";

    // An unitialized variable.
    Importance importance;

    // Call Enum.TryParse method.
    if (Enum.TryParse(value, out importance))
    {
        // We now have an enum type.
        Console.WriteLine(importance == Importance.Medium);
    }
    }
}

Reference : http://www.dotnetperls.com/enum-parse

参考:http://www.dotnetperls.com/enum-parse

#6


I have an optimised implementation you could use in UnconstrainedMelody. Effectively it's just caching the list of names, but it's doing so in a nice, strongly typed, generically constrained way :)

我有一个可以在UnconstrainedMelody中使用的优化实现。实际上,它只是缓存了名称列表,但它是以一种漂亮的,强类型的,通用约束的方式实现的:)

#7


enum EnumStatus
{
    NAO_INFORMADO = 0,
    ENCONTRADO = 1,
    BLOQUEADA_PELO_ENTREGADOR = 2,
    DISPOSITIVO_DESABILITADO = 3,
    ERRO_INTERNO = 4,
    AGARDANDO = 5
}

...

if (Enum.TryParse<EnumStatus>(item.status, out status)) {

}

#8


There's currently no out of the box Enum.TryParse. This has been requested on Connect (Still no Enum.TryParse) and got a response indicating possible inclusion in the next framework after .NET 3.5. You'll have to implement the suggested workarounds for now.

目前没有开箱即用的Enum.TryParse。这已经在Connect(仍然没有Enum.TryParse)上被请求,并得到一个响应,表明可能包含在.NET 3.5之后的下一个框架中。您现在必须实施建议的解决方法。

#9


The only way to avoid exception handling is to use the GetNames() method, and we all know that exceptions shouldn't be abused for common application logic :)

避免异常处理的唯一方法是使用GetNames()方法,我们都知道异常不应该被滥用于常见的应用程序逻辑:)

#10


Is caching a dynamically generated function/dictionary permissable?

缓存动态生成的函数/字典是否允许?

Because you don't (appear to) know the type of the enum ahead of time, the first execution could generate something subsequent executions could take advantage of.

因为您没有(似乎)提前知道枚举的类型,所以第一次执行可以生成后续执行可以利用的内容。

You could even cache the result of Enum.GetNames()

你甚至可以缓存Enum.GetNames()的结果

Are you trying to optimize for CPU or Memory? Do you really need to?

您是否尝试优化CPU或内存?你真的需要吗?

#11


As others already said, if you don't use Try&Catch, you need to use IsDefined or GetNames... Here are some samples...they basically are all the same, the first one handling nullable enums. I prefer the 2nd one as it's an extension on strings, not enums...but you can mix them as you want!

正如其他人已经说过的,如果你不使用Try&Catch,你需要使用IsDefined或GetNames ...这里有一些样本......它们基本上都是一样的,第一个处理可以为空的枚举。我更喜欢第二个,因为它是字符串的扩展,而不是枚举...但你可以根据需要混合它们!

  • www.objectreference.net/post/Enum-TryParse-Extension-Method.aspx
  • flatlinerdoa.spaces.live.com/blog/cns!17124D03A9A052B0!605.entry
  • mironabramson.com/blog/post/2008/03/Another-version-for-the-missing-method-EnumTryParse.aspx
  • lazyloading.blogspot.com/2008/04/enumtryparse-with-net-35-extension.html

#12


There is not a TryParse because the Enum's type is not known until runtime. A TryParse that follows the same methodology as say the Date.TryParse method would throw an implicit conversion error on the ByRef parameter.

没有TryParse,因为Enum的类型直到运行时才知道。 TryParse遵循与Date.TryParse方法相同的方法,会在ByRef参数上引发隐式转换错误。

I suggest doing something like this:

我建议做这样的事情:

//1 line call to get value
MyEnums enumValue = (Sections)EnumValue(typeof(Sections), myEnumTextValue, MyEnums.SomeEnumDefault);

//Put this somewhere where you can reuse
public static object EnumValue(System.Type enumType, string value, object NotDefinedReplacement)
{
    if (Enum.IsDefined(enumType, value)) {
        return Enum.Parse(enumType, value);
    } else {
        return Enum.Parse(enumType, NotDefinedReplacement);
    }
}

#13


Have a look at the Enum class (struct ? ) itself. There is a Parse method on that but I'm not sure about a tryparse.

看看Enum类(struct?)本身。有一个Parse方法,但我不确定tryparse。

#14


This method will convert a type of enum:

此方法将转换一种枚举:

  public static TEnum ToEnum<TEnum>(object EnumValue, TEnum defaultValue)
    {
        if (!Enum.IsDefined(typeof(TEnum), EnumValue))
        {
            Type enumType = Enum.GetUnderlyingType(typeof(TEnum));
            if ( EnumValue.GetType() == enumType )
            {
                string name = Enum.GetName(typeof(HLink.ViewModels.ClaimHeaderViewModel.ClaimStatus), EnumValue);
                if( name != null)
                    return (TEnum)Enum.Parse(typeof(TEnum), name);
                return defaultValue;
            }
        }
        return (TEnum)Enum.Parse(typeof(TEnum), EnumValue.ToString());
    } 

It checks the underlying type and get the name against it to parse. If everything fails it will return default value.

它检查基础类型并获取其名称以进行解析。如果一切都失败了,它将返回默认值。

#1


As others have said, you have to implement your own TryParse. Simon Mourier is providing a full implementation which takes care of everything.

正如其他人所说,你必须实现自己的TryParse。 Simon Mourier正在提供一个完整的实现,它可以处理所有事情。

If you are using bitfield enums (i.e. flags), you also have to handle a string like "MyEnum.Val1|MyEnum.Val2" which is a combination of two enum values. If you just call Enum.IsDefined with this string, it will return false, even though Enum.Parse handles it correctly.

如果您正在使用位域枚举(即标志),您还必须处理像“MyEnum.Val1 | MyEnum.Val2”这样的字符串,它是两个枚举值的组合。如果你只是用这个字符串调用Enum.IsDefined,它将返回false,即使Enum.Parse正确处理它。

Update

As mentioned by Lisa and Christian in the comments, Enum.TryParse is now available for C# in .NET4 and up.

MSDN Docs

正如Lisa和Christian在评论中所提到的,Enum.TryParse现在可用于.NET4及更高版本的C#。 MSDN文档

#2


Enum.IsDefined will get things done. It may not be as efficient as a TryParse would probably be, but it will work without exception handling.

Enum.IsDefined将完成任务。它可能不如TryParse那样有效,但它可以在没有异常处理的情况下工作。

public static TEnum ToEnum<TEnum>(this string strEnumValue, TEnum defaultValue)
{
    if (!Enum.IsDefined(typeof(TEnum), strEnumValue))
        return defaultValue;

    return (TEnum)Enum.Parse(typeof(TEnum), strEnumValue);
}

Worth noting: a TryParse method was added in .NET 4.0.

值得注意的是:.NET 4.0中添加了TryParse方法。

#3


Here is a custom implementation of EnumTryParse. Unlike other common implementations, it also supports enum marked with the Flags attribute.

这是EnumTryParse的自定义实现。与其他常见实现不同,它还支持使用Flags属性标记的枚举。

    /// <summary>
    /// Converts the string representation of an enum to its Enum equivalent value. A return value indicates whether the operation succeeded.
    /// This method does not rely on Enum.Parse and therefore will never raise any first or second chance exception.
    /// </summary>
    /// <param name="type">The enum target type. May not be null.</param>
    /// <param name="input">The input text. May be null.</param>
    /// <param name="value">When this method returns, contains Enum equivalent value to the enum contained in input, if the conversion succeeded.</param>
    /// <returns>
    /// true if s was converted successfully; otherwise, false.
    /// </returns>
    public static bool EnumTryParse(Type type, string input, out object value)
    {
        if (type == null)
            throw new ArgumentNullException("type");

        if (!type.IsEnum)
            throw new ArgumentException(null, "type");

        if (input == null)
        {
            value = Activator.CreateInstance(type);
            return false;
        }

        input = input.Trim();
        if (input.Length == 0)
        {
            value = Activator.CreateInstance(type);
            return false;
        }

        string[] names = Enum.GetNames(type);
        if (names.Length == 0)
        {
            value = Activator.CreateInstance(type);
            return false;
        }

        Type underlyingType = Enum.GetUnderlyingType(type);
        Array values = Enum.GetValues(type);
        // some enums like System.CodeDom.MemberAttributes *are* flags but are not declared with Flags...
        if ((!type.IsDefined(typeof(FlagsAttribute), true)) && (input.IndexOfAny(_enumSeperators) < 0))
            return EnumToObject(type, underlyingType, names, values, input, out value);

        // multi value enum
        string[] tokens = input.Split(_enumSeperators, StringSplitOptions.RemoveEmptyEntries);
        if (tokens.Length == 0)
        {
            value = Activator.CreateInstance(type);
            return false;
        }

        ulong ul = 0;
        foreach (string tok in tokens)
        {
            string token = tok.Trim(); // NOTE: we don't consider empty tokens as errors
            if (token.Length == 0)
                continue;

            object tokenValue;
            if (!EnumToObject(type, underlyingType, names, values, token, out tokenValue))
            {
                value = Activator.CreateInstance(type);
                return false;
            }

            ulong tokenUl;
            switch (Convert.GetTypeCode(tokenValue))
            {
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.SByte:
                    tokenUl = (ulong)Convert.ToInt64(tokenValue, CultureInfo.InvariantCulture);
                    break;

                //case TypeCode.Byte:
                //case TypeCode.UInt16:
                //case TypeCode.UInt32:
                //case TypeCode.UInt64:
                default:
                    tokenUl = Convert.ToUInt64(tokenValue, CultureInfo.InvariantCulture);
                    break;
            }

            ul |= tokenUl;
        }
        value = Enum.ToObject(type, ul);
        return true;
    }

    private static char[] _enumSeperators = new char[] { ',', ';', '+', '|', ' ' };

    private static object EnumToObject(Type underlyingType, string input)
    {
        if (underlyingType == typeof(int))
        {
            int s;
            if (int.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(uint))
        {
            uint s;
            if (uint.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(ulong))
        {
            ulong s;
            if (ulong.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(long))
        {
            long s;
            if (long.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(short))
        {
            short s;
            if (short.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(ushort))
        {
            ushort s;
            if (ushort.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(byte))
        {
            byte s;
            if (byte.TryParse(input, out s))
                return s;
        }

        if (underlyingType == typeof(sbyte))
        {
            sbyte s;
            if (sbyte.TryParse(input, out s))
                return s;
        }

        return null;
    }

    private static bool EnumToObject(Type type, Type underlyingType, string[] names, Array values, string input, out object value)
    {
        for (int i = 0; i < names.Length; i++)
        {
            if (string.Compare(names[i], input, StringComparison.OrdinalIgnoreCase) == 0)
            {
                value = values.GetValue(i);
                return true;
            }
        }

        if ((char.IsDigit(input[0]) || (input[0] == '-')) || (input[0] == '+'))
        {
            object obj = EnumToObject(underlyingType, input);
            if (obj == null)
            {
                value = Activator.CreateInstance(type);
                return false;
            }
            value = obj;
            return true;
        }

        value = Activator.CreateInstance(type);
        return false;
    }

#4


In the end you have to implement this around Enum.GetNames:

最后,你必须围绕Enum.GetNames实现这个:

public bool TryParseEnum<T>(string str, bool caseSensitive, out T value) where T : struct {
    // Can't make this a type constraint...
    if (!typeof(T).IsEnum) {
        throw new ArgumentException("Type parameter must be an enum");
    }
    var names = Enum.GetNames(typeof(T));
    value = (Enum.GetValues(typeof(T)) as T[])[0];  // For want of a better default
    foreach (var name in names) {
        if (String.Equals(name, str, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase)) {
            value = (T)Enum.Parse(typeof(T), name);
            return true;
        }
    }
    return false;
}

Additional notes:

  • Enum.TryParse is included in .NET 4. See here http://msdn.microsoft.com/library/dd991876(VS.100).aspx
  • Enum.TryParse包含在.NET 4中。请参见http://msdn.microsoft.com/library/dd991876(VS.100).aspx

  • Another approach would be to directly wrap Enum.Parse catching the exception thrown when it fails. This could be faster when a match is found, but will likely to slower if not. Depending on the data you are processing this may or may not be a net improvement.
  • 另一种方法是直接包装Enum.Parse捕获失败时抛出的异常。找到匹配项时可能会更快,但如果没有,则可能会更慢。根据您正在处理的数据,这可能是也可能不是净改进。


EDIT: Just seen a better implementation on this, which caches the necessary information: http://damieng.com/blog/2010/10/17/enums-better-syntax-improved-performance-and-tryparse-in-net-3-5

编辑:刚刚看到一个更好的实现,它缓存了必要的信息:http://damieng.com/blog/2010/10/17/enums-better-syntax-improved-performance-and-tryparse-in-net- 3-5

#5


Based on .NET 4.5

基于.NET 4.5

Sample code below

示例代码如下

using System;

enum Importance
{
    None,
    Low,
    Medium,
    Critical
}

class Program
{
    static void Main()
    {
    // The input value.
    string value = "Medium";

    // An unitialized variable.
    Importance importance;

    // Call Enum.TryParse method.
    if (Enum.TryParse(value, out importance))
    {
        // We now have an enum type.
        Console.WriteLine(importance == Importance.Medium);
    }
    }
}

Reference : http://www.dotnetperls.com/enum-parse

参考:http://www.dotnetperls.com/enum-parse

#6


I have an optimised implementation you could use in UnconstrainedMelody. Effectively it's just caching the list of names, but it's doing so in a nice, strongly typed, generically constrained way :)

我有一个可以在UnconstrainedMelody中使用的优化实现。实际上,它只是缓存了名称列表,但它是以一种漂亮的,强类型的,通用约束的方式实现的:)

#7


enum EnumStatus
{
    NAO_INFORMADO = 0,
    ENCONTRADO = 1,
    BLOQUEADA_PELO_ENTREGADOR = 2,
    DISPOSITIVO_DESABILITADO = 3,
    ERRO_INTERNO = 4,
    AGARDANDO = 5
}

...

if (Enum.TryParse<EnumStatus>(item.status, out status)) {

}

#8


There's currently no out of the box Enum.TryParse. This has been requested on Connect (Still no Enum.TryParse) and got a response indicating possible inclusion in the next framework after .NET 3.5. You'll have to implement the suggested workarounds for now.

目前没有开箱即用的Enum.TryParse。这已经在Connect(仍然没有Enum.TryParse)上被请求,并得到一个响应,表明可能包含在.NET 3.5之后的下一个框架中。您现在必须实施建议的解决方法。

#9


The only way to avoid exception handling is to use the GetNames() method, and we all know that exceptions shouldn't be abused for common application logic :)

避免异常处理的唯一方法是使用GetNames()方法,我们都知道异常不应该被滥用于常见的应用程序逻辑:)

#10


Is caching a dynamically generated function/dictionary permissable?

缓存动态生成的函数/字典是否允许?

Because you don't (appear to) know the type of the enum ahead of time, the first execution could generate something subsequent executions could take advantage of.

因为您没有(似乎)提前知道枚举的类型,所以第一次执行可以生成后续执行可以利用的内容。

You could even cache the result of Enum.GetNames()

你甚至可以缓存Enum.GetNames()的结果

Are you trying to optimize for CPU or Memory? Do you really need to?

您是否尝试优化CPU或内存?你真的需要吗?

#11


As others already said, if you don't use Try&Catch, you need to use IsDefined or GetNames... Here are some samples...they basically are all the same, the first one handling nullable enums. I prefer the 2nd one as it's an extension on strings, not enums...but you can mix them as you want!

正如其他人已经说过的,如果你不使用Try&Catch,你需要使用IsDefined或GetNames ...这里有一些样本......它们基本上都是一样的,第一个处理可以为空的枚举。我更喜欢第二个,因为它是字符串的扩展,而不是枚举...但你可以根据需要混合它们!

  • www.objectreference.net/post/Enum-TryParse-Extension-Method.aspx
  • flatlinerdoa.spaces.live.com/blog/cns!17124D03A9A052B0!605.entry
  • mironabramson.com/blog/post/2008/03/Another-version-for-the-missing-method-EnumTryParse.aspx
  • lazyloading.blogspot.com/2008/04/enumtryparse-with-net-35-extension.html

#12


There is not a TryParse because the Enum's type is not known until runtime. A TryParse that follows the same methodology as say the Date.TryParse method would throw an implicit conversion error on the ByRef parameter.

没有TryParse,因为Enum的类型直到运行时才知道。 TryParse遵循与Date.TryParse方法相同的方法,会在ByRef参数上引发隐式转换错误。

I suggest doing something like this:

我建议做这样的事情:

//1 line call to get value
MyEnums enumValue = (Sections)EnumValue(typeof(Sections), myEnumTextValue, MyEnums.SomeEnumDefault);

//Put this somewhere where you can reuse
public static object EnumValue(System.Type enumType, string value, object NotDefinedReplacement)
{
    if (Enum.IsDefined(enumType, value)) {
        return Enum.Parse(enumType, value);
    } else {
        return Enum.Parse(enumType, NotDefinedReplacement);
    }
}

#13


Have a look at the Enum class (struct ? ) itself. There is a Parse method on that but I'm not sure about a tryparse.

看看Enum类(struct?)本身。有一个Parse方法,但我不确定tryparse。

#14


This method will convert a type of enum:

此方法将转换一种枚举:

  public static TEnum ToEnum<TEnum>(object EnumValue, TEnum defaultValue)
    {
        if (!Enum.IsDefined(typeof(TEnum), EnumValue))
        {
            Type enumType = Enum.GetUnderlyingType(typeof(TEnum));
            if ( EnumValue.GetType() == enumType )
            {
                string name = Enum.GetName(typeof(HLink.ViewModels.ClaimHeaderViewModel.ClaimStatus), EnumValue);
                if( name != null)
                    return (TEnum)Enum.Parse(typeof(TEnum), name);
                return defaultValue;
            }
        }
        return (TEnum)Enum.Parse(typeof(TEnum), EnumValue.ToString());
    } 

It checks the underlying type and get the name against it to parse. If everything fails it will return default value.

它检查基础类型并获取其名称以进行解析。如果一切都失败了,它将返回默认值。