将值解析为可为空的枚举
Parsing value into nullable enumeration
假设我有这个:
PriorityType? priority;
string userInput = ...;
我无法更改其定义方式:PriorityType? priority
因为它实际上是与另一段代码的合同的一部分。
我试过了,但没用:
if (Enum.TryParse<PriorityType?>(userInput, out priority)) {
正确的方法是什么?
最简单的方法:
PriorityType tempPriority;
PriorityType? priority;
if (Enum.TryParse<PriorityType>(userInput, out tempPriority))
priority = tempPriority;
这是我能想到的最好的:
public static class NullableEnum
{
public static bool TryParse<T>(string value, out T? result) where T :struct, IConvertible
{
if (!typeof(T).IsEnum)
throw new Exception("This method is only for Enums");
T tempResult = default(T);
if (Enum.TryParse<T>(value, out tempResult))
{
result = tempResult;
return true;
}
result = null;
return false;
}
}
使用:
if (NullableEnum.TryParse<PriorityType>(userInput, out priority))
上面的 class 可以像 Enum.TryParse
一样使用,除了可以为 null 的输入。您可以添加另一个采用不可为 null 的 T
的重载函数,以便您可以根据需要在两种情况下使用它。不幸的是,扩展方法在枚举类型上效果不佳(就我在短时间内尝试操作它而言)。
这是 posted by Ron Beyer 稍作重构:
public static class NullableEnum
{
public static bool TryParse<T>(string value, out T? result) where T : struct, IConvertible
{
if (!typeof(T).IsEnum) throw new ArgumentException("Invalid Enum");
result = Enum.TryParse(value, out T tempResult) ? tempResult : default(T?);
return (result == null) ? false : true;
}
}
如果你希望它是一行代码,你可以这样做:
var priority = Enum.TryParse<PriorityType>(userInput, out var outPriority) ? outPriority : (PriorityType?) null;
这里的另一种方法实际上可以让您处理可为 null 的枚举,而不是在获取它们时失败:
public static class EnumHelper {
public static TEnum Parse<TEnum>( string value ){
if( typeof(TEnum).IsEnum )
return (TEnum)Enum.Parse( typeof(TEnum), value );
Type? nullableType = Nullable.GetUnderlyingType( typeof(TEnum) );
if( /*not a nullable type*/nullableType is null )
throw new ArgumentException( $"Provided type {typeof(TEnum).Name} must be either an enum or a nullable enum" );
return (TEnum?)Enum.Parse( nullableType, value );
}
}
调用模式与使用 out
参数的基本库略有不同,但如果您愿意,可以将其包装在相同的调用模式中。对于大多数情况,以上往往更容易处理。
假设我有这个:
PriorityType? priority;
string userInput = ...;
我无法更改其定义方式:PriorityType? priority
因为它实际上是与另一段代码的合同的一部分。
我试过了,但没用:
if (Enum.TryParse<PriorityType?>(userInput, out priority)) {
正确的方法是什么?
最简单的方法:
PriorityType tempPriority;
PriorityType? priority;
if (Enum.TryParse<PriorityType>(userInput, out tempPriority))
priority = tempPriority;
这是我能想到的最好的:
public static class NullableEnum
{
public static bool TryParse<T>(string value, out T? result) where T :struct, IConvertible
{
if (!typeof(T).IsEnum)
throw new Exception("This method is only for Enums");
T tempResult = default(T);
if (Enum.TryParse<T>(value, out tempResult))
{
result = tempResult;
return true;
}
result = null;
return false;
}
}
使用:
if (NullableEnum.TryParse<PriorityType>(userInput, out priority))
上面的 class 可以像 Enum.TryParse
一样使用,除了可以为 null 的输入。您可以添加另一个采用不可为 null 的 T
的重载函数,以便您可以根据需要在两种情况下使用它。不幸的是,扩展方法在枚举类型上效果不佳(就我在短时间内尝试操作它而言)。
这是
public static class NullableEnum
{
public static bool TryParse<T>(string value, out T? result) where T : struct, IConvertible
{
if (!typeof(T).IsEnum) throw new ArgumentException("Invalid Enum");
result = Enum.TryParse(value, out T tempResult) ? tempResult : default(T?);
return (result == null) ? false : true;
}
}
如果你希望它是一行代码,你可以这样做:
var priority = Enum.TryParse<PriorityType>(userInput, out var outPriority) ? outPriority : (PriorityType?) null;
这里的另一种方法实际上可以让您处理可为 null 的枚举,而不是在获取它们时失败:
public static class EnumHelper {
public static TEnum Parse<TEnum>( string value ){
if( typeof(TEnum).IsEnum )
return (TEnum)Enum.Parse( typeof(TEnum), value );
Type? nullableType = Nullable.GetUnderlyingType( typeof(TEnum) );
if( /*not a nullable type*/nullableType is null )
throw new ArgumentException( $"Provided type {typeof(TEnum).Name} must be either an enum or a nullable enum" );
return (TEnum?)Enum.Parse( nullableType, value );
}
}
调用模式与使用 out
参数的基本库略有不同,但如果您愿意,可以将其包装在相同的调用模式中。对于大多数情况,以上往往更容易处理。