列挙型を文字列に変換


163

.NET 3.5で列挙型を文字列に変換するための好ましい方法はどれですか?

  • Enum.GetName
  • 列挙型フォーマット
  • ToString

なぜこれらの1つを他よりも優先する必要があるのですか?パフォーマンスは良いですか?


10
検索したところ、重複は見つかりませんでした。リンクを提供していただける場合は、この質問を削除します。
Eric Weilnau、2009年

1
場合によっては、switchステートメントを使用することがベストプラクティスではない(大きな列挙がある場合)代わりにDict <>を使用できます
Guy L

1
より良いパフォーマンスが必要な場合は、この記事codeproject.com/KB/dotnet/enum.aspxで説明されているクラスを使用できます。使用法は次のようになりますEnum <YourEnum> .ToString(yourValue)またはEnum <YourEnum> .ToString((int)yourValue)
ideafixxxer

5
dotfuscationを壊さないようにコーディングすることは、犬を振る尾の縮図です。SWプロデューサーは「dotfuscatorが何かをするために素晴らしいアプリを作ろう」とは考えていません。ソフトウェア開発の促進に役立つDofuscatorが存在します。それができない場合は...できます!
micahhoover 2014

回答:


125

C#6以降、列挙型の名前を取得する最良の方法は新しいnameof演算子です。

nameof(MyEnum.EnumValue);

// Ouputs
> "EnumValue"

これはコンパイル時に機能し、enumはコンパイル結果の文字列に置き換えられます。つまり、これが可能な限り最速の方法です。

列挙型名の難読化に価値がある、または重要であると考える場合、列挙型名を使用するとコードの難読化が妨げられます。これはおそらく他の問題です。


11
これはもっと注目に値します。それにもかかわらず明らかな制限、つまりコンパイル時の入力の要件。私の意見では、これは可能な限り好まれるべきです。「名前の変更」と「すべての参照を検索」では、これも考慮に入れられ、マジックストリングと定数の重複が回避される可能性があります。
ティモ

1
実行時に列挙値が定義されていると機能しないと思いますか?例:MyEnum variableEnum; variableEnum = setEnumValueMethod(); nameof(variableEnum);
マクスター

1
ノー@Maxter、などnameof(variableEnum)となります"variableEnum"。(ビルド時に)valueではなく、field / property / param / variable の名前を反映します
キース

あなたがた。残念ながら、これを行うと機能しません。var someEnumvalue = SomeEnum.FooBar; nameof(someEnumvalue);
Squibly

@間違いなくはい、それは戻り"someEnumValue"ますがnameof(SomeEnum.FooBar)、取得する必要があります"FooBar"
キース、

93

私たちのプロジェクトのために働く...

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

7
Enum.GetNameは、オブジェクトの引数として値を受け取ります。これは、値がボックス化され、割り当てとガベージコレクションでCPUリソースを浪費することを意味します。これが長時間行われる場合、Enum.GetNameは、値をディクショナリにキャッシュしてそこから名前を探すよりもはるかに低いスループットになります。
2014年

@Ranでは、代わりに使用するソリューションは何ですか?
shaijut

これが答えなければなりません
Squibly

プロジェクトが遅くなります。toString()の方が高速です。
d2k2

29

私のテストで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()

25

Enum.GetName(...)

これは、そのための最もエレガントな方法です。

var enumValueString = Enum.GetName(typeof (MyEnum), MyEnum.MyValue);

通話.ToString()時間は短いので問題ありません。

var enumValueString = MyEnum.MyValue.ToString();

新しいC#6構文では、次を使用できます。

nameof(MyEnum.MyValue)

20

これらすべては内部的にと呼ばれるメソッドを呼び出すことになりInternalGetValueAsStringます。との違いはToString、最初にいくつかのことを確認するGetName必要があることですGetName

  1. 入力したタイプはnullではありません。
  2. 入力したタイプは実際には列挙型です。
  3. 渡された値はnullではありません。
  4. 渡された値は、列挙型が基になる型として実際に使用できる型、または列挙型自体の型です。これGetTypeをチェックするために値を使用します。

.ToString.ToStringメソッドには同じ検証の問題がないため、渡されたバージョンではなく、クラス自体のインスタンスで呼び出されるため、上記の問題を心配する必要はありません。静的メソッドとして、それ.ToStringが文字列として値を取得する最も速い方法であると私は結論づけます。


2
どこでチェックしたの?アセンブリバージョンは何でしたか?非常に異なる結果が得られます。
nawfal 2013年

17

私が見つけることができる最高のものは、MSDN上のこの無関係な質問です。この質問に回答するXMLスニペットが含まれています。これらのメソッドのいずれにも同じ欠陥があります。それらはを呼び出しますがenum.toString()Dotfuscationを使用すると正しく機能しません。。その他の懸念は、間接的なボクシング(GetNameおよびFormat)に関連しているようです。残念ながら、上記のいずれを使用してもパフォーマンス上の理由はわかりません。

xmlスニペットからの言い換え、

ボックス化された列挙型をstring.Format()または他の関数に渡すと、enum.ToString()呼び出される可能性があります。これにより、Dotfuscating時に問題が発生します。あなたは使用しないでくださいenum.ToString()enum.GetNames()enum.GetName()enum.Format()またはenum.Parse()文字列に列挙型を変換します。代わりに、switchステートメントを使用し、必要に応じて名前を国際化してください。


16

Enum.GetName()

Format()実際にはGetName()、いくつかのフォーマット機能を備えた(またはInternalGetValueAsString()正確に言えば)単なるラッパーです。ToString()とほぼ同じFormat()です。GetName()ソースを読む人にとって何をするのかは完全に明らかなので、私は最良の選択肢だと思います。


8

「説明」拡張メソッドを作成し、それを列挙型にアタッチして、スペースと大文字小文字を含む本当にユーザーフレンドリーな名前を付けることができるようにします。enum値自体を表示可能なテキストとして使用するのは好きではありません。それは、開発者がより読みやすいコードを作成するために使用するものだからです。UI表示を目的としたものではありません。列挙型全体を変更することなくUIを変更できるようにしたいと考えています。


6

「推奨」方法が何であるかはわかりません(100人に質問し、100の異なる意見を得る)が、最も簡単で効果的な方法を実行します。 GetName動作しますが、より多くのキーストロークが必要です。 ToString()とてもうまくやっているようです。


1

VB愛好家の場合:

EnumStringValue = System.Enum.GetName(GetType(MyEnum), MyEnumValue)

0

これも機能します。

    List<string> names = Enum.GetNames(typeof(MyEnum)).ToList();

0

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


-2

シンプル:名前をリストに列挙:

List<String> NameList = Enum.GetNames(typeof(YourEnumName)).Cast<string>().ToList()

こんにちは@ Brian、GetNames()の出力をキャストする必要はないと思います
Nic
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.