Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将字符串解析为枚举类型_C#_.net_Generics_Enums - Fatal编程技术网

C# 将字符串解析为枚举类型

C# 将字符串解析为枚举类型,c#,.net,generics,enums,C#,.net,Generics,Enums,我有一个枚举类型,例如: public Enum MyEnum { enum1, enum2, enum3 }; 我将从配置文件中读取一个字符串。我需要的是将字符串解析为MyEnum类型、null或未定义。不确定以下代码是否有效(很抱歉,现在无法访问我的VS): //示例:ParseEnum(“ENUM1”,ref eVal); bool ParseEnum(字符串值1,参考值),其中T:Enum { 布尔-布雷特=假; var x=从Enum.GetNames(typeof(T))中

我有一个枚举类型,例如:

public Enum MyEnum {
    enum1, enum2, enum3 };
我将从配置文件中读取一个字符串。我需要的是将字符串解析为MyEnum类型、null或未定义。不确定以下代码是否有效(很抱歉,现在无法访问我的VS):

//示例:ParseEnum(“ENUM1”,ref eVal);
bool ParseEnum(字符串值1,参考值),其中T:Enum
{
布尔-布雷特=假;
var x=从Enum.GetNames(typeof(T))中的x开始,其中
string.Equals(value1,x,StringComparison.OrdinalIgnoreCase)
选择x;
如果(x.Count()==1)
{
eVal=Enum.Parse(typeof(T),x.Item(0))作为T;
bRet=真;
}
返回布雷特;
}

不确定它是否正确,或者是否有任何其他简单的方法将字符串解析为MyEnum值?

类似于:

public static class EnumUtils
{
    public static Nullable<T> Parse<T>(string input) where T : struct
    {
        //since we cant do a generic type constraint
        if (!typeof(T).IsEnum)
        {
            throw new ArgumentException("Generic Type 'T' must be an Enum");
        }
        if (!string.IsNullOrEmpty(input))
        {
            if (Enum.GetNames(typeof(T)).Any(
                  e => e.Trim().ToUpperInvariant() == input.Trim().ToUpperInvariant()))
            {
                return (T)Enum.Parse(typeof(T), input, true);
            }
        }
        return null;
    }
}
公共静态类枚举
{
公共静态可空解析(字符串输入),其中T:struct
{
//因为我们不能做泛型类型约束
if(!typeof(T).IsEnum)
{
抛出新ArgumentException(“泛型类型“T”必须是枚举”);
}
如果(!string.IsNullOrEmpty(输入))
{
if(Enum.GetNames(typeof(T)).Any(
e=>e.Trim().ToUpperInvariant()==input.Trim().ToUpperInvariant())
{
返回(T)Enum.Parse(typeof(T),输入,true);
}
}
返回null;
}
}
用作:

MyEnum? value = EnumUtils.Parse<MyEnum>("foo");
MyEnum?value=EnumUtils.Parse(“foo”); (注意:旧版本使用了
try/catch
around
Enum.Parse

如果您使用的是.NET 3.5(甚至是2.0,如果您删掉了扩展方法),我很幸运地掌握了本文中的技术:

枚举和字符串-停止疯狂

编辑:域已消失,现在是链接场。我在工作时从我们的代码库中提取了代码(经过一段时间的轻微修改和添加),您现在可以在这里找到:


我在中有一个
TryParseName
方法,一个用于委托和枚举实用程序方法的库,它通过一些后期构建技巧使用“无法表达”的约束。(为了清楚起见,使用库的代码不需要后期生成。)

您可以这样使用它:

Foo foo;
bool parsed = Enums.TryParseName<Foo>(name, out foo);
Foo-Foo;
bool parsed=Enums.TryParseName(名称,out foo);
我目前没有一个不区分大小写的版本,但如果您需要,我可以很容易地介绍一个。请注意,这不会像内置版本那样尝试解析数字,例如“12”,也不会尝试解析逗号分隔的标志列表。稍后我可能会添加标志版本,但我看不出数字版本有什么意义

这是在没有装箱和执行时间类型检查的情况下完成的。拥有约束非常方便:)


请告诉我您是否发现不区分大小写的解析有用…

我刚刚将中的语法与中的异常处理结合起来,创建了以下内容:

public static class Enum<T>
{
    public static T Parse(string value)
    {
        //Null check
        if(value == null) throw new ArgumentNullException("value");
        //Empty string check
        value = value.Trim();
        if(value.Length == 0) throw new ArgumentException("Must specify valid information for parsing in the string", "value");
        //Not enum check
        Type t = typeof(T);
        if(!t.IsEnum) throw new ArgumentException("Type provided must be an Enum", "TEnum");

        return (T)Enum.Parse(typeof(T), value);
    }
}
公共静态类枚举
{
公共静态T解析(字符串值)
{
//空检查
如果(value==null)抛出新的ArgumentNullException(“value”);
//空字符串检查
value=value.Trim();
如果(value.Length==0)抛出新的ArgumentException(“必须在字符串中指定用于解析的有效信息”,“value”);
//非枚举检查
类型t=类型(t);
如果(!t.IsEnum)抛出新的ArgumentException(“提供的类型必须是枚举”,“TEnum”);
返回(T)Enum.Parse(typeof(T),value);
}
}

您可以稍微旋转它以返回null,而不是抛出异常。

如果您想避免使用try/catch,可以使用
TryParse

MyEnum eVal;
if (Enum.TryParse("ENUM2", true, out eVal)){
    // now eVal is the enumeration element: enum2 
}
//unable to parse. You can log the error, exit, redirect, etc...
我对选定的答案稍加修改。我希望你喜欢

public static class EnumUtils
{
    public static Nullable<T> Parse<T>(string input) where T : struct
    {
        //since we cant do a generic type constraint
        if (!typeof(T).IsEnum)
        {
            throw new ArgumentException("Generic Type 'T' must be an Enum");
        }

        int intVal;
        if (!string.IsNullOrEmpty(input) && !int.TryParse(input, out intVal))
        {
            T eVal;
            if (Enum.TryParse(input, true, out eVal))
            {
                return eVal;
            }
        }
        return null;
    }
}
公共静态类枚举
{
公共静态可空解析(字符串输入),其中T:struct
{
//因为我们不能做泛型类型约束
if(!typeof(T).IsEnum)
{
抛出新ArgumentException(“泛型类型“T”必须是枚举”);
}
int intVal;
如果(!string.IsNullOrEmpty(输入)和&!int.TryParse(输入,输出intVal))
{
T评价;
if(Enum.TryParse(输入、真、输出求值))
{
返回评估;
}
}
返回null;
}
}

这是一个老问题,但现在.NET 4.5已经有了。

要按字符串返回枚举,如果包含:

    public static T GetEnum<T>(string s)
    {
        Array arr = Enum.GetValues(typeof(T));
        foreach (var x in arr)
        {
            if (x.ToString().Contains(s))
                return (T)x;
        }
        return default(T);
    }
publicstatict GetEnum(字符串s)
{
数组arr=Enum.GetValues(typeof(T));
foreach(arr中的var x)
{
如果(x.ToString().包含)
返回(T)x;
}
返回默认值(T);
}

@Mark我知道,但在这样的情况下确实很容易:)@Mark确实很有道理-try/catch很少是个好主意。编辑后的版本比问题中的版本效率更高,因为它只进行一次部分枚举,而不是最多3次。确保T:Enum的泛型类型约束在这里也很有用,否则,Enum.GetNames可能会引发错误。很遗憾,这是不可能的-类型约束不能是Enum。一个增强是将input.ToUpperInvariant()更改为(input???).Trim()。Toupper不变量()。这将避免空异常。@Jon Skeet,您可以引入额外的重载方法,让用户可以选择是否区分大小写。@Joh Skeet,不确定您的方法是否应该是(name,ref foo)。如果tryparse失败,foo应该是什么?第一个枚举值?我认为最好让用户对其进行初始化,如果失败则不进行更改。我知道您试图使此方法与TryParse(name,out value)保持一致。如果
TryParse
失败,它将是
default(Foo)
,它与
TryParse
TryGetValue
等保持一致。如果我不追求一致性,我可能会返回一个
null
。我将考虑为不区分大小写的匹配引入一个新的重载,或者可能使用StringComparer(或类似的)来允许文化差异
MyEnum eVal;
if (Enum.TryParse("ENUM2", true, out eVal)){
    // now eVal is the enumeration element: enum2 
}
//unable to parse. You can log the error, exit, redirect, etc...
public static class EnumUtils
{
    public static Nullable<T> Parse<T>(string input) where T : struct
    {
        //since we cant do a generic type constraint
        if (!typeof(T).IsEnum)
        {
            throw new ArgumentException("Generic Type 'T' must be an Enum");
        }

        int intVal;
        if (!string.IsNullOrEmpty(input) && !int.TryParse(input, out intVal))
        {
            T eVal;
            if (Enum.TryParse(input, true, out eVal))
            {
                return eVal;
            }
        }
        return null;
    }
}
    public static T GetEnum<T>(string s)
    {
        Array arr = Enum.GetValues(typeof(T));
        foreach (var x in arr)
        {
            if (x.ToString().Contains(s))
                return (T)x;
        }
        return default(T);
    }