Help us understand the problem. What is going on with this article?

Enum制約下のジェネリック・クラスでenumとintの相互キャスト (C#)

前提

  • C# 7.3

やりたいこと

  • ジェネリックなenumを扱うクラスclass <TEnum> where TEnum : System.Enumで、TEnumintを相互に変換したい。

できなかったこと

普通にキャストしてみたところ、コンパイラが「このキャストはできない」とエラーを吐きました。

public class EnumeratedArray<TEnum, TObj> where TEnum : Enum {
    private TObj [] objects;
    public TObj this [TEnum n] { get { return objects [(int) n]; } } // エラー
    public TEnum this [TObj o] { get { return (TEnum) Array.IndexOf (objects, o); } } // エラー
}
// この例は、やりたいことを端的に表現したもので、やりたいことそのものではありません。

通常であれば、intとenumの相互キャストは可能なはずで、ジェネリックだからできないのでしょうね。

できたこと

System.Objectとの変換メソッドを使いました。

public class EnumeratedArray<TEnum, TObj> where TEnum : Enum {
    private TObj [] objects;
    public TObj this [TEnum n] { get { return objects [Convert.ToInt32 (n)]; } }
    public TEnum this [TObj o] { get { return (TEnum) Enum.ToObject (typeof (TEnum), Array.IndexOf (objects, o)); } }
}

とはいえ、この方法なら、型制約がなくても(7.3未満でも)書けてしまうんですね。

わかったこと

  • C# 7.3でEnum制約が書けるようになったけど、存外と制限が厳しい。

蛇足

EnumeratedList.cs
using System;
using System.Collections.Generic;

/// <summary>EnumでインデックスするList</summary>
/// <typeparam name="TEnum">インデックスの型</typeparam>
/// <typeparam name="TObj">要素の型</typeparam>
public class EnumeratedList<TEnum, TObj> : List<TObj> where TEnum : Enum {

    /// <summary>インデックスが範囲内か調べる</summary>
    public bool ContainsKey (TEnum n) {
        var index = Convert.ToInt32 (n);
        return (index >= 0 && index < this.Count);
    }

    /// <summary>正引き</summary>
    public TObj this [TEnum n] => this [Convert.ToInt32 (n)];

    /// <summary>逆引き</summary>
    public TEnum EnumOf (TObj o) => (TEnum) Enum.ToObject (typeof (TEnum), this.IndexOf (o));

}

素直にDictionary<TEnum, TObj>を使っておけと言われそうですね。

参考

以下を参考にさせていただきました。

いつもありがとうございます。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away