.NET 3.5で列挙型を文字列に変換するための好ましい方法はどれですか?
- Enum.GetName
- 列挙型フォーマット
- ToString
なぜこれらの1つを他よりも優先する必要があるのですか?パフォーマンスは良いですか?
.NET 3.5で列挙型を文字列に変換するための好ましい方法はどれですか?
なぜこれらの1つを他よりも優先する必要があるのですか?パフォーマンスは良いですか?
回答:
C#6以降、列挙型の名前を取得する最良の方法は新しいnameof
演算子です。
nameof(MyEnum.EnumValue);
// Ouputs
> "EnumValue"
これはコンパイル時に機能し、enumはコンパイル結果の文字列に置き換えられます。つまり、これが可能な限り最速の方法です。
列挙型名の難読化に価値がある、または重要であると考える場合、列挙型名を使用するとコードの難読化が妨げられます。これはおそらく他の問題です。
nameof(variableEnum)
となります"variableEnum"
。(ビルド時に)valueではなく、field / property / param / variable の名前を反映します。
"someEnumValue"
ますがnameof(SomeEnum.FooBar)
、取得する必要があります"FooBar"
。
私たちのプロジェクトのために働く...
public static String convertToString(this Enum eff)
{
return Enum.GetName(eff.GetType(), eff);
}
public static EnumType converToEnum<EnumType>(this String enumValue)
{
return (EnumType) Enum.Parse(typeof(EnumType), enumValue);
}
私のテストでEnum.GetName
は、より速く、まともなマージンでした。内部的にToString
呼び出しますEnum.GetName
。.NET 4.0のソースからの基本事項:
public override String ToString()
{
return Enum.InternalFormat((RuntimeType)GetType(), GetValue());
}
private static String InternalFormat(RuntimeType eT, Object value)
{
if (!eT.IsDefined(typeof(System.FlagsAttribute), false))
{
String retval = GetName(eT, value); //<== the one
if (retval == null)
return value.ToString();
else
return retval;
}
else
{
return InternalFlagsFormat(eT, value);
}
}
それが確かな理由だとは言えませんが、テストは一方が他方より速いと述べています。どちらの呼び出しにもボクシングが含まれ(実際はリフレクション呼び出しであり、基本的にフィールド名を取得しています)、好みに応じて遅くなる可能性があります。
テストのセットアップ:8つの値を持つ列挙型。反復数= 1000000
結果:Enum.GetName => 700 ms、ToString => 2000 ms
速度が目立たない場合ToString
は、よりクリーンな呼び出しを提供するため、気にしません。コントラスト
Enum.GetName(typeof(Bla), value)
と
value.ToString()
これらすべては内部的にと呼ばれるメソッドを呼び出すことになりInternalGetValueAsString
ます。との違いはToString
、最初にいくつかのことを確認するGetName
必要があることですGetName
。
GetType
をチェックするために値を使用します。.ToString
.ToString
メソッドには同じ検証の問題がないため、渡されたバージョンではなく、クラス自体のインスタンスで呼び出されるため、上記の問題を心配する必要はありません。静的メソッドとして、それ.ToString
が文字列として値を取得する最も速い方法であると私は結論づけます。
私が見つけることができる最高のものは、MSDN上のこの無関係な質問です。この質問に回答するXMLスニペットが含まれています。これらのメソッドのいずれにも同じ欠陥があります。それらはを呼び出しますがenum.toString()
、Dotfuscationを使用すると正しく機能しません。。その他の懸念は、間接的なボクシング(GetNameおよびFormat)に関連しているようです。残念ながら、上記のいずれを使用してもパフォーマンス上の理由はわかりません。
xmlスニペットからの言い換え、
ボックス化された列挙型をstring.Format()または他の関数に渡すと、
enum.ToString()
呼び出される可能性があります。これにより、Dotfuscating時に問題が発生します。あなたは使用しないでくださいenum.ToString()
、enum.GetNames()
、enum.GetName()
、enum.Format()
またはenum.Parse()
文字列に列挙型を変換します。代わりに、switchステートメントを使用し、必要に応じて名前を国際化してください。
「説明」拡張メソッドを作成し、それを列挙型にアタッチして、スペースと大文字小文字を含む本当にユーザーフレンドリーな名前を付けることができるようにします。enum値自体を表示可能なテキストとして使用するのは好きではありません。それは、開発者がより読みやすいコードを作成するために使用するものだからです。UI表示を目的としたものではありません。列挙型全体を変更することなくUIを変更できるようにしたいと考えています。
ToString()
読みやすさの観点から最も明白な結果を与える一方で、Enum.GetName()
するとすると、何をしようとしているのかをすばやく理解するために、少しずつメンタルパースが必要になります(常にパターンが表示されない限り)。
純粋なパフォーマンスの観点からは、@ nawfalの回答ですでに提供されているように、Enum.GetName()
より優れています。
ただし、パフォーマンスが本当に目標である場合は、事前にルックアップを提供することをお勧めします(ディクショナリまたはその他のマッピングを使用)。
C ++ / CLIでは、これは次のようになります。
Dictionary<String^, MyEnum> mapping;
for each (MyEnum field in Enum::GetValues(MyEnum::typeid))
{
mapping.Add(Enum::GetName(MyEnum::typeid), field);
}
100アイテムの列挙と1000000回の反復を使用した比較:
Enum.GetName:〜800ms
.ToString():〜1600ms
辞書マッピング:〜250ms