6468


新人の方に`enum`が持つ全ての値を`foreach`で取得しようとしてたら、  
エラーが出たと質問されました。

[code]

    public enum TopCities
    {
        Tokyo,
    
        Yokohama,
    
        Osaka,
    
        Nagoya,
    
        Sapporo,
    
        Kobe,
    
        Kyoto
    }
    
    #endregion
    
    #region Public Methods and Operators
    
    public void LoopThroughAllTopCities()
    {
        foreach (string city in Enum.GetValues(TopCities))
        {
            ltlResult.Text += city + "\r\n";
        }
    }
    
    #endregion
    
    #region Methods
    
    protected void Page_Load(object sender, EventArgs e)
    {
        LoopThroughAllTopCities();
    }
    
    #endregion
    
[/code]

このエラーが出てコンパイルできないと聞かれました。

> TopCities' is a 'type' but is used like a 'variable'

この場合[`Enum.GetValues`の引数は`System.Type`](http://referencesource.microsoft.com/#mscorlib/system/enum.cs,20fa909ef3233d20,references)なので、`typeof(TopCities)`を渡すべきです。

![画像の説明をここに入力](https://i.stack.imgur.com/dAyQR.png)

[code]

    foreach (var city in Enum.GetValues(typeof(TopCities)))
    
[/code]

もしくは

[code]

    foreach (var city in Enum.GetNames(typeof(TopCities)))
    
[/code]

で都市名の取得もできますと答えました。

`Enum.GetValues`と`Enum.GetNames`の違いは指定した値を持つ指定した列挙体にある定数の名前を取得する代わりに、定数の値の配列を取得することです。

そこで思ったのですが、どのようなの場合にどちらのメソッドが推奨されるのかを聞きたいです。


CC BY-SA 3.0
2015-02-13T23:29:11.350
6466
2015-08-22T06:16:26.603
2015-02-14T00:10:10.733
5750
5987
question
c# .net
GetValues とGetNamesでenumが持つ全ての値をforeachで取得する場合、どちらが推奨されるのですか？


名称だけでよいのであれば`Enum.GetNames`、数値と名称が必要であれば`Enum.GetValues`、各フィールドでリフレクションを行うのであれば`Type.GetFields`を使用べきかと思います。

質問の例で`Enum.GetValues`を使用すると`Enum.ToString`の呼び出しコストがかかるので`Enum.GetNames`が適切です。しかし

[code]

    public enum TopCities
    {
        [DisplayName("東京")]
        Tokyo,
        [DisplayName("横浜")]
        Yokohama,
    }
    
[/code]

のように属性が適用されていてそれを参照したいのであれば`Type.GetFields`となります。


CC BY-SA 3.0
2015-02-14T00:01:05.497
6468
2015-02-14T00:01:05.497
5750
6466
answer


まったく違うメソッドです。  
GetValues()はenumを返しGetNames()はstringを返します。  
あなたが必要な方を使うことをオススメします。  
詳しくはMSDNを調べてください。


CC BY-SA 3.0
2015-02-14T00:11:38.513
6469
2015-08-22T06:16:26.603
2015-08-22T06:16:26.603
10945
5005
6466
answer


そもそもenumには重複した値を設定できます。

[code]

    enum Value {
        One = 1,
        Alias = Value.One,
        Two = 2,
    }
    
[/code]

この例ではGetNames()は "One", "Alias", "Two" を返しますし、GetValues()は 1, 1, 2 を返します。  
名前の通りですので、後は適材適所で選択してください。


CC BY-SA 3.0
2015-02-14T02:42:38.783
6471
2015-02-14T02:42:38.783
4236
6466
answer