回答:
.NET Coreおよび.NET> 4 には、汎用の解析メソッドがあります。
Enum.TryParse("Active", out StatusEnum myStatus);
これには、C#7の新しいインラインout
変数も含まれるため、これはtry-parse、明示的な列挙型への変換、およびmyStatus
変数の初期化と入力を行います。
C#7と最新の.NETにアクセスできる場合、これが最善の方法です。
.NETでは、それは(4以上になるまで)かなり醜いです:
StatusEnum MyStatus = (StatusEnum) Enum.Parse(typeof(StatusEnum), "Active", true);
私はこれを簡単にする傾向があります:
public static T ParseEnum<T>(string value)
{
return (T) Enum.Parse(typeof(T), value, true);
}
その後、私は行うことができます:
StatusEnum MyStatus = EnumUtil.ParseEnum<StatusEnum>("Active");
コメントで提案されている1つのオプションは、十分に簡単な拡張機能を追加することです。
public static T ToEnum<T>(this string value)
{
return (T) Enum.Parse(typeof(T), value, true);
}
StatusEnum MyStatus = "Active".ToEnum<StatusEnum>();
最後に、文字列を解析できない場合に使用するデフォルトの列挙型が必要になる場合があります。
public static T ToEnum<T>(this string value, T defaultValue)
{
if (string.IsNullOrEmpty(value))
{
return defaultValue;
}
T result;
return Enum.TryParse<T>(value, true, out result) ? result : defaultValue;
}
これはこれを呼び出しにします:
StatusEnum MyStatus = "Active".ToEnum(StatusEnum.None);
ただし、このような拡張メソッドstring
を(名前空間の制御なしで)string
enumを保持するかどうかのすべてのインスタンスに表示されるように(1234.ToString().ToEnum(StatusEnum.None)
有効ですが無意味です)ように注意して追加します。多くの場合、開発チーム全体がこれらの拡張機能の機能を十分に理解していない限り、非常に特定のコンテキストにのみ適用される追加のメソッドでMicrosoftのコアクラスが乱雑にならないようにするのが最善です。
使用Enum.TryParse<T>(String, T)
(≥.NET 4.0):
StatusEnum myStatus;
Enum.TryParse("Active", out myStatus);
C#7.0のパラメータータイプのインライン化により、さらに簡素化できます。
Enum.TryParse("Active", out StatusEnum myStatus);
Parse
変換で問題が発生した場合(値がnull
、空、または対応する列挙定数がない場合)の説明的な例外をスローします。これは、TryParse
ブール値の戻り値(具体的なエラーを抑制する)よりも優れています
var result = Enum.TryParse<System.DayOfWeek>("55", out var parsedEnum);
Enum.Parse()
リフレクションを介して実装されるため、パフォーマンスはひどいことに注意してください。(同じEnum.ToString
ことが、反対方向にも当てはまります)にも当てはまります。
パフォーマンスに敏感なコードで文字列をEnumに変換する必要がある場合はDictionary<String,YourEnum>
、起動時にat を作成し、それを使用して変換を行うのが最善の方法です。
Enum.Parseを探しています。
SomeEnum enum = (SomeEnum)Enum.Parse(typeof(SomeEnum), "EnumValue");
ここで拡張メソッドを使用できます。
public static T ToEnum<T>(this string value, bool ignoreCase = true)
{
return (T) Enum.Parse(typeof (T), value, ignoreCase);
}
そして、あなたは以下のコードでそれらを呼び出すことができます(ここでFilterType
は、列挙型です):
FilterType filterType = type.ToEnum<FilterType>();
注意:
enum Example
{
One = 1,
Two = 2,
Three = 3
}
Enum.(Try)Parse()
複数のコンマ区切りの引数を受け入れ、それらをバイナリの 'or'と組み合わせます|
。あなたはこれを無効にすることはできませんし、私の意見ではほとんどそれを望んでいません。
var x = Enum.Parse("One,Two"); // x is now Three
Three
定義されていない場合x
でも、int値を取得します3
。さらに悪いことです。Enum.Parse()は、列挙型に対しても定義されていない値を与える可能性があります。
私は、ユーザーの結果を喜んでまたは望まずに体験して、この動作を引き起こしたくありません。
さらに、他の人が述べたように、パフォーマンスは大きな列挙型にとって理想的ではありません。つまり、可能な値の数が線形です。
私は以下を提案します:
public static bool TryParse<T>(string value, out T result)
where T : struct
{
var cacheKey = "Enum_" + typeof(T).FullName;
// [Use MemoryCache to retrieve or create&store a dictionary for this enum, permanently or temporarily.
// [Implementation off-topic.]
var enumDictionary = CacheHelper.GetCacheItem(cacheKey, CreateEnumDictionary<T>, EnumCacheExpiration);
return enumDictionary.TryGetValue(value.Trim(), out result);
}
private static Dictionary<string, T> CreateEnumDictionary<T>()
{
return Enum.GetValues(typeof(T))
.Cast<T>()
.ToDictionary(value => value.ToString(), value => value, StringComparer.OrdinalIgnoreCase);
}
Enum.(Try)Parse accepts multiple, comma-separated arguments, and combines them with binary 'or'
ます。列挙値を2の累乗として設定でき、複数のブールフラグを解析する非常に簡単な方法があることを意味します。「UseSSL、NoRetries、Sync」。実際、それはおそらくそれがそのために設計されたものです。
Enum.Parseはあなたの友達です:
StatusEnum MyStatus = (StatusEnum)Enum.Parse(typeof(StatusEnum), "Active");
受け入れられた回答をデフォルト値で拡張して、例外を回避できます。
public static T ParseEnum<T>(string value, T defaultValue) where T : struct
{
try
{
T enumValue;
if (!Enum.TryParse(value, true, out enumValue))
{
return defaultValue;
}
return enumValue;
}
catch (Exception)
{
return defaultValue;
}
}
次に、次のように呼び出します。
StatusEnum MyStatus = EnumUtil.ParseEnum("Active", StatusEnum.None);
デフォルト値が列挙型でない場合、Enum.TryParseは失敗し、キャッチされる例外をスローします。
多くの場所でコードでこの関数を何年も使用した後、この操作にはパフォーマンスが必要であることを示す情報を追加するとよいでしょう。
defaultValue
およびメソッドの戻り値の型は両方ともですT
。タイプが異なる場合は、コンパイル時エラー「「ConsoleApp1.Size」から「ConsoleApp1.Color」に変換できません」などのタイプが返されます。
.NET 4.5のtry / catchおよびTryParse()メソッドなしで文字列をTEnumに解析します。
/// <summary>
/// Parses string to TEnum without try/catch and .NET 4.5 TryParse()
/// </summary>
public static bool TryParseToEnum<TEnum>(string probablyEnumAsString_, out TEnum enumValue_) where TEnum : struct
{
enumValue_ = (TEnum)Enum.GetValues(typeof(TEnum)).GetValue(0);
if(!Enum.IsDefined(typeof(TEnum), probablyEnumAsString_))
return false;
enumValue_ = (TEnum) Enum.Parse(typeof(TEnum), probablyEnumAsString_);
return true;
}
拡張メソッドソリューションが好きです。
namespace System
{
public static class StringExtensions
{
public static bool TryParseAsEnum<T>(this string value, out T output) where T : struct
{
T result;
var isEnum = Enum.TryParse(value, out result);
output = isEnum ? result : default(T);
return isEnum;
}
}
}
以下は、テストによる私の実装です。
using static Microsoft.VisualStudio.TestTools.UnitTesting.Assert;
using static System.Console;
private enum Countries
{
NorthAmerica,
Europe,
Rusia,
Brasil,
China,
Asia,
Australia
}
[TestMethod]
public void StringExtensions_On_TryParseAsEnum()
{
var countryName = "Rusia";
Countries country;
var isCountry = countryName.TryParseAsEnum(out country);
WriteLine(country);
IsTrue(isCountry);
AreEqual(Countries.Rusia, country);
countryName = "Don't exist";
isCountry = countryName.TryParseAsEnum(out country);
WriteLine(country);
IsFalse(isCountry);
AreEqual(Countries.NorthAmerica, country); // the 1rst one in the enumeration
}
public static T ParseEnum<T>(string value) //function declaration
{
return (T) Enum.Parse(typeof(T), value);
}
Importance imp = EnumUtil.ParseEnum<Importance>("Active"); //function call
====================完全なプログラム====================
using System;
class Program
{
enum PetType
{
None,
Cat = 1,
Dog = 2
}
static void Main()
{
// Possible user input:
string value = "Dog";
// Try to convert the string to an enum:
PetType pet = (PetType)Enum.Parse(typeof(PetType), value);
// See if the conversion succeeded:
if (pet == PetType.Dog)
{
Console.WriteLine("Equals dog.");
}
}
}
-------------
Output
Equals dog.
私はクラスを使用しました(構文解析とパフォーマンスの改善を伴うEnumの厳密に型指定されたバージョン)。GitHubで見つけました。.NET3.5でも動作するはずです。辞書をバッファリングするため、メモリのオーバーヘッドが多少あります。
StatusEnum MyStatus = Enum<StatusEnum>.Parse("Active");
ブログ投稿はEnumsです– NET 3.5での構文の改善、パフォーマンスの向上、TryParse。
そしてコード:https : //github.com/damieng/DamienGKit/blob/master/CSharp/DamienG.Library/System/EnumT.cs
パフォーマンスのために、これは役立つかもしれません:
private static Dictionary<Type, Dictionary<string, object>> dicEnum = new Dictionary<Type, Dictionary<string, object>>();
public static T ToEnum<T>(this string value, T defaultValue)
{
var t = typeof(T);
Dictionary<string, object> dic;
if (!dicEnum.ContainsKey(t))
{
dic = new Dictionary<string, object>();
dicEnum.Add(t, dic);
foreach (var en in Enum.GetValues(t))
dic.Add(en.ToString(), en);
}
else
dic = dicEnum[t];
if (!dic.ContainsKey(value))
return defaultValue;
else
return (T)dic[value];
}
ここでは、EnumMember値を持つenum値のケースは考慮されていないことがわかりました。だからここに行きます:
using System.Runtime.Serialization;
public static TEnum ToEnum<TEnum>(this string value, TEnum defaultValue) where TEnum : struct
{
if (string.IsNullOrEmpty(value))
{
return defaultValue;
}
TEnum result;
var enumType = typeof(TEnum);
foreach (var enumName in Enum.GetNames(enumType))
{
var fieldInfo = enumType.GetField(enumName);
var enumMemberAttribute = ((EnumMemberAttribute[]) fieldInfo.GetCustomAttributes(typeof(EnumMemberAttribute), true)).FirstOrDefault();
if (enumMemberAttribute?.Value == value)
{
return Enum.TryParse(enumName, true, out result) ? result : defaultValue;
}
}
return Enum.TryParse(value, true, out result) ? result : defaultValue;
}
そしてその列挙型の例:
public enum OracleInstanceStatus
{
Unknown = -1,
Started = 1,
Mounted = 2,
Open = 3,
[EnumMember(Value = "OPEN MIGRATE")]
OpenMigrate = 4
}
Enumからオブジェクト値を取得するには、Enum.Parseを使用する必要があります。その後、オブジェクト値を特定の列挙値に変更する必要があります。列挙値へのキャストは、Convert.ChangeTypeを使用して行うことができます。次のコードスニペットをご覧ください
public T ConvertStringValueToEnum<T>(string valueToParse){
return Convert.ChangeType(Enum.Parse(typeof(T), valueToParse, true), typeof(T));
}
このサンプルを試してください:
public static T GetEnum<T>(string model)
{
var newModel = GetStringForEnum(model);
if (!Enum.IsDefined(typeof(T), newModel))
{
return (T)Enum.Parse(typeof(T), "None", true);
}
return (T)Enum.Parse(typeof(T), newModel.Result, true);
}
private static Task<string> GetStringForEnum(string model)
{
return Task.Run(() =>
{
Regex rgx = new Regex("[^a-zA-Z0-9 -]");
var nonAlphanumericData = rgx.Matches(model);
if (nonAlphanumericData.Count < 1)
{
return model;
}
foreach (var item in nonAlphanumericData)
{
model = model.Replace((string)item, "");
}
return model;
});
}
このサンプルでは、すべての文字列を送信し、を設定できますEnum
。あなたの場合はEnum
持っていたデータはあなたが望んでいたことを、あなたのように、そのを返すEnum
タイプ。
newModel
各行で上書きしているので、ダッシュが含まれている場合、置換されません。また、あなたは文字列が何も含まれているかどうかをチェックする必要はありません、あなただけ呼び出すことができますReplace
とにかく:var newModel = model.Replace("-", "").Replace(" ", "");
これがいつ追加されたかはわかりませんが、Enumクラスには
Parse<TEnum>(stringValue)
問題の例でそのように使用されます:
var MyStatus = Enum.Parse<StatusEnum >("Active")
または大文字小文字を区別しない:
var MyStatus = Enum.Parse<StatusEnum >("active", true)
これが使用する逆コンパイルされたメソッドは次のとおりです。
[NullableContext(0)]
public static TEnum Parse<TEnum>([Nullable(1)] string value) where TEnum : struct
{
return Enum.Parse<TEnum>(value, false);
}
[NullableContext(0)]
public static TEnum Parse<TEnum>([Nullable(1)] string value, bool ignoreCase) where TEnum : struct
{
TEnum result;
Enum.TryParse<TEnum>(value, ignoreCase, true, out result);
return result;
}
プロパティ名があなたがそれを呼びたいものと異なる場合(すなわち言語の違い)、あなたはこのようにすることができます:
MyType.cs
using System;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
[JsonConverter(typeof(StringEnumConverter))]
public enum MyType
{
[EnumMember(Value = "person")]
Person,
[EnumMember(Value = "annan_deltagare")]
OtherPerson,
[EnumMember(Value = "regel")]
Rule,
}
EnumExtensions.cs
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public static class EnumExtensions
{
public static TEnum ToEnum<TEnum>(this string value) where TEnum : Enum
{
var jsonString = $"'{value.ToLower()}'";
return JsonConvert.DeserializeObject<TEnum>(jsonString, new StringEnumConverter());
}
public static bool EqualsTo<TEnum>(this string strA, TEnum enumB) where TEnum : Enum
{
TEnum enumA;
try
{
enumA = strA.ToEnum<TEnum>();
}
catch
{
return false;
}
return enumA.Equals(enumB);
}
}
Program.cs
public class Program
{
static public void Main(String[] args)
{
var myString = "annan_deltagare";
var myType = myString.ToEnum<MyType>();
var isEqual = myString.EqualsTo(MyType.OtherPerson);
//Output: true
}
}