Skip to content

Instantly share code, notes, and snippets.

@matarillo
Last active August 29, 2015 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matarillo/3dfe836a5cfdd6198baa to your computer and use it in GitHub Desktop.
Save matarillo/3dfe836a5cfdd6198baa to your computer and use it in GitHub Desktop.

Javaによる高階型変数の実装 ... のC#版(序)

System.Web.HttpSessionStateが典型例だが、グローバルな辞書オブジェクトがIDictionary<string, object>型だったりする。そうすると、こんなのをよく見る。

public static class FooKeys
{
    public const string Key1 = "FooKeys.Key1";
    public const string Key2 = "FooKeys.Key2";
    ...
}

public static class BarKeys
{
    public const string Key1 = "BarKeys.Key1";
    public const string Key2 = "BarKeys.Key2";
    ...
}

こんな感じで、Foo関係のキーとBar関係のキーがバッティングしないように、キー文字列に規約を持ち込んだりして。 でもこれって型安全じゃないよね。

辞書がグローバルだからつらいのかもしれない。Foo関係の辞書とBar関係の辞書が別インスタンスになってれば、キーがバッティングする危険性は下げられるだろう。

public readonly Dictionary<string, object> FooDictionary = new Dictionary<string, object>();
public readonly Dictionary<string, object> BarDictionary = new Dictionary<string, object>();

でもこれも型安全じゃないよね。

Foo関係のキーとBar関係のキーが別の型なら、もうすこしましかもしれない。 いっそ列挙型ならどうだろう。

public enum FooKeys
{
    Key1, Key2, //...
}

public enum BarKeys
{
    Key1, Key2, //...
}

public readonly Dictionary<FooKeys, object> FooDictionary = new Dictionary<FooKeys, object>();
public readonly Dictionary<BarKeys, object> BarDictionary = new Dictionary<BarKeys, object>();

ところで、TValueobject型なのも型安全ではない。 たとえばstring型を格納する場合とint型を格納する場合があったらどうするのがいいか。

public enum FooStringKeys
{
    Key1, Key2, //...
}

public enum FooIntKeys
{
    Key1, Key2, //...
}

public readonly Dictionary<FooStringKeys, string> FooStringDictionary = new Dictionary<FooStringKeys, string>();
public readonly Dictionary<FooIntKeys, int> FooIntDictionary = new Dictionary<FooIntKeys, int>();

まあこうやって並べるのが簡単ではある。 でも、もっと工夫はできないのか。

たとえば、var dict = DictionaryGroup<FooKeys>みたいな型のオブジェクトがあって、 dict.Add<int>(FooKeys.IntKeys.Key1, 123); とか、string value = dict.Get<string>(FooKeys.StringKeys.Key2);とかできないか。(イメージはジェネリックなインデクサなんだけど、C#では実現できないので、Add<T>()Get<T>()で代用している)

その場合、dict.Add<int>()dict.Get<int>()FooKeys.StringKeys型を渡すコードはコンパイルエラーにできないか。

そしてもちろん、dictに対してBarKeys.IntKeys型やBarKeys.StringKeys型を渡すコードはコンパイルエラーにできないか。

というような話は、あとでまた書く。 (追記)書いた。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment