Genericsの中のStaticフィールドに関するコト
わかってみれば、当たり前だけど、ちと疑問に思って調べたコトを備忘録的に。
まずは、以下のようなコードがあったとして、
public class Hoge<T> { public static int Value = 0; } class MainEntry { static void Main(string[] args) { Hoge<Type>.Value = 200; Hoge<Int32>.Value = 300; Console.WriteLine(Hoge<Exception>.Value); } }
このときどーなる買って話でして。。。結論から先に言うと、0がConsoleに出力される。
これは、規格で決まっていて、JIS X3015:2006の、25.1.4が根拠。*1
規格で決まってるのならしょーがないとはいえ、何でこんな風になっているのか自分なりに考えてみた。
多分、以下のようなこーどを許容するためじゃ無いかと思う。
public class Piyo<T> { public static T Value = default(T); }
この場合、静的フィールドの"Value"フィールドは型引数に依存するので、別個に初期化されないとおかしなコトになる。なので、このような規格になってるんだと思う。
んだは、オープン型のHoge
非ジェネリック型からジェネリック型を派生させることで行けるんじゃ無いかと。*2
public class Hoge { public static int Value; } public class HogeEx<T> : Hoge { } class MainEntry { static void Main(string[] args) { HogeEx<Type>.Value = 200; HogeEx<Int32>.Value = 300; Console.WriteLine(HogeEx<Exception>.Value); } }
こうすることで、オープン型HogeEx
蛇足ながら、以下のようにしたとしても、別個になるので、注意。あくまでもオープン型の内側にある主体は全てクローズ型個別に生成されると言うことなのかも
public class Piyo<T> { private class Inner { public static int Value; } public static int Value { get { return Inner.Value; } set { Inner.Value = value; } } } class MainEntry { static void Main(string[] args) { Piyo<Type>.Value = 200; Piyo<Int32>.Value = 300; Console.WriteLine(Piyo<Exception>.Value); }
このサンプルだと、Inncerはprivateなので、外部から不可視だけど、例えばこれがpublicになってたとき、結局アクセスするためには、Piyo
あと、外部定義の型をシングルトンにするなり、元から、static classにするなりして、そいつを参照させるなんて方法も無くは無いと思うけど*3これだと、アクセシビリティが厄介なことになる*4ので、あんまりおすすめできないかも。