有沒有人有解析枚舉更優雅的解決方案?以下對我來說似乎是一團糟。優雅地解析C#枚舉
UserType userType = (UserType)Enum.Parse(typeof(UserType), iUserType.ToString());
有沒有人有解析枚舉更優雅的解決方案?以下對我來說似乎是一團糟。優雅地解析C#枚舉
UserType userType = (UserType)Enum.Parse(typeof(UserType), iUserType.ToString());
我經常做一個通用的幫手吧:
public static T ParseEnum<T>(string value) where T:struct
{
return (T)Enum.Parse(typeof(T), value);
}
可以結合起來,與Jon Skeet'sUnstrained Melody(或任何其他職位IL處理器),以獲得在枚舉適當類型的約束,但是可選的。
然後你可以使用它像這樣:
var enumValue = ParseEnum<UserType>(iUserType.ToString());
.NET框架4.0還帶有Enum.TryParse
這也提供了類似的語法,並提供一種方法來處理,如果解析失敗。例如:
UserType userType;
if (Enum.TryParse<UserType>(iUserType.ToString(), out userType))
{
//Yay! Parse succeeded. The userType variable has the value.
}
else
{
//Oh noes! The parse failed!
}
您可以創建這樣
public static class EnumExtensions
{
public static T ToEnum<T>(this string s)
{
return (T)Enum.Parse(typeof(T), s);
}
}
的extesion方法,然後在代碼中,你可以使用這種方式(MyEnum包含值A和B):
string s = "B";
MyEnum e = s.ToEnum<MyEnum>();
以下是基於@vcsjones版本和反饋的擴展方法,以及來自@Mones示例:
public enum TestEnum
{
None,
A,
B,
};
void Main()
{
var testValues = new List<object>();
testValues.AddRange(Enumerable.Range(-2, 6).Select(i => (object)i));
testValues.AddRange(new List<string>() { String.Empty, "A", "B", "C", null });
foreach (var testValue in testValues)
{
Console.WriteLine($"Testing value {testValue ?? String.Empty}:");
TestEnum output;
var enumValues = Enum.GetNames(typeof(TestEnum)).ToList();
try
{
if (TestEnum.TryParse(testValue.ToString(), out output))
{
Console.WriteLine($"Succeeded with TryParse on {testValue} to {output}");
}
else
{
Console.WriteLine($"Failed to TryParse on {testValue}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Test harness caught an exception: {ex.ToString()}");
}
var toEnumOutput = (testValue ?? String.Empty).ToString().Parse<TestEnum>();
Console.WriteLine($"Parse<TEnum> returned {toEnumOutput}");
Console.WriteLine();
Console.WriteLine();
}
}
public static class EnumExtensions
{
public static TEnum Parse<TEnum>(this string value) where TEnum : struct
{
TEnum output = default(TEnum);
var enumValues = Enum.GetNames(typeof(TEnum)).ToList();
if (Enum.TryParse<TEnum>(value, true, out output))
if (Enum.IsDefined(typeof(TEnum), value) || value.ToString().Contains(",") || enumValues.Contains(output.ToString()))
{
Console.WriteLine($"Converted '{value}' to {output}.");
return output;
}
else
{
Console.WriteLine($"{value} is not an underlying value of the enumeration.");
}
else
{
Console.WriteLine($"{value} is not a member of the enumeration.");
}
return default(TEnum);
}
}
個
測試工具給出了這樣的輸出:
Testing value -2:
Succeeded with TryParse on -2 to -2
-2 is not an underlying value of the enumeration.
Parse<TEnum> returned None
Testing value -1:
Succeeded with TryParse on -1 to -1
-1 is not an underlying value of the enumeration.
Parse<TEnum> returned None
Testing value 0:
Succeeded with TryParse on 0 to None
Converted '0' to None.
Parse<TEnum> returned None
Testing value 1:
Succeeded with TryParse on 1 to A
Converted '1' to A.
Parse<TEnum> returned A
Testing value 2:
Succeeded with TryParse on 2 to B
Converted '2' to B.
Parse<TEnum> returned B
Testing value 3:
Succeeded with TryParse on 3 to 3
3 is not an underlying value of the enumeration.
Parse<TEnum> returned None
Testing value :
Failed to TryParse on
is not a member of the enumeration.
Parse<TEnum> returned None
Testing value A:
Succeeded with TryParse on A to A
Converted 'A' to A.
Parse<TEnum> returned A
Testing value B:
Succeeded with TryParse on B to B
Converted 'B' to B.
Parse<TEnum> returned B
Testing value C:
Failed to TryParse on C
C is not a member of the enumeration.
Parse<TEnum> returned None
Testing value :
Test harness caught an exception: System.NullReferenceException: Object reference not set to an instance of an object.
at UserQuery.Main() in C:\Users\Colin\AppData\Local\Temp\3\LINQPad5\_zhvrhwll\query_ludjga.cs:line 49
is not a member of the enumeration.
Parse<TEnum> returned None
參考文獻:
我看到你在努力創造一個研究得很好的答案和一套很好的測試。這真的很棒,但讓我鼓勵你嘗試使用一些單元測試框架。任何一個,他們這些年都很相似。我很想用** xUnit **(我真的很喜歡那個,只是鏈接一個nuget而不用去)來重寫你的測試,告訴你它有多酷/可讀,但是..可能你會受益更多自己做。如果你想嘗試一些東西,請給我留言。 – quetzalcoatl 2017-10-10 18:40:52
嗨@quetzalcoatl - 欣賞反饋。我添加nUnit測試,然後發佈一個鏈接到我的測試類。 – Colin 2017-10-10 20:33:39
哦我碰到泰勒·布林克利的來到圖書館做這個和更多!
這另一個StackOverflow答案Generic version of Enum.Parse in C#導致Jon Skeet的Unconstrained Melody圖書館網站,其中指示我們改爲Enums.NET。哇。
我注意到對於Enum.TryParse(),解析永遠不會失敗,即使我希望它的值不在枚舉中。 我的例子是:https://pastebin.com/fZfT69Lk – Colin 2017-10-07 00:47:04
@Colin - 有趣。這是因爲整數值總是可以轉換爲枚舉值,例如'(TestEnum)4737373'也可以工作和編譯。如果你想強制你的值是一個命名值,你可以使用GetNames來確保它在那裏。 – vcsjones 2017-10-07 12:24:10