前提
- C# 7.3
やりたいこと
- ジェネリックなenumを扱うクラス
class <TEnum> where TEnum : System.Enum
で、TEnum
とint
を相互に変換したい。
できなかったこと
普通にキャストしてみたところ、コンパイラが「このキャストはできない」とエラーを吐きました。
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>
を使っておけと言われそうですね。
参考
以下を参考にさせていただきました。
- New C# 7.3 feature allowing Enum as a generic type constraint is useless as implemented - Developer Community
- C# によるプログラミング入門 > [オブジェクト指向] ジェネリック > C# 7.3 での追加 ~ ++C++; // 未確認飛行 C
いつもありがとうございます。