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