web-dev-qa-db-ja.com

C#で定数辞書を作成する

stringsからintsへのconstant(実行時に変更しない)マッピングを作成する最も効率的な方法は何ですか?

const Dictionary を使用してみましたが、うまくいきませんでした。

適切なセマンティクスで immutable wrapper を実装できましたが、それでも完全に正しいとは思えません。


尋ねた人のために、私は IDataErrorInfo を生成されたクラスに実装し、columnNameが記述子の配列をルックアップする方法を探しています。

私はスイッチが文字列を受け入れることを認識していませんでした(テスト時のタイプミス!)ので、これを使用します。ありがとう!

113
David Schmitt

本当にコンパイル時に生成される定数辞書をC#で作成することは、実際には簡単な作業ではありません。実際、ここでの答えはどれもそれを実際に達成しません。

ただし、必ずしもニースとは限りませんが、要件を満たすソリューションが1つあります。 C#仕様によると、switch-caseテーブルは定数ハッシュジャンプテーブルにコンパイルされることに注意してください。つまり、これらは定数辞書であり、一連のif-elseステートメントではありません。したがって、次のようなswitch-caseステートメントを検討してください。

switch (myString)
{
   case "cat": return 0;
   case "dog": return 1;
   case "elephant": return 3;
}

これはまさにあなたが望むものです。そして、はい、私は知っている、それはいです。

167
Tamas Czinege

現在のフレームワークには、不変のコレクションがほとんどありません。 .NET 3.5の比較的簡単なオプションの1つを考えることができます。

Enumerable.ToLookup()を使用します- Lookup<,> クラスは不変です(ただし、rhsでは複数値)。 Dictionary<,>から非常に簡単にこれを行うことができます。

    Dictionary<string, int> ids = new Dictionary<string, int> {
      {"abc",1}, {"def",2}, {"ghi",3}
    };
    ILookup<string, int> lookup = ids.ToLookup(x => x.Key, x => x.Value);
    int i = lookup["def"].Single();
36
Marc Gravell
enum Constants
{
    Abc = 1,
    Def = 2,
    Ghi = 3
}

...

int i = (int)Enum.Parse(typeof(Constants), "Def");
14
Richard Poole

これは、「CONST辞書」に最も近いものです。

public static int GetValueByName(string name)
{
    switch (name)
    {
        case "bob": return 1;
        case "billy": return 2;
        default: return -1;
    }
}

コンパイラーは、コードを可能な限りクリーンにビルドするのに十分なほどスマートです。

10
Timothy Khouri

4.5+ Frameworkを使用している場合、ReadOnlyDictionary(リストにはReadOnlyコレクションも使用)を使用して、読み取り専用のマッピング/定数を実行します。以下の方法で実装されています。

static class SomeClass
{
    static readonly ReadOnlyDictionary<string,int> SOME_MAPPING 
        = new ReadOnlyDictionary<string,int>(
            new Dictionary<string,int>()
            {
                { "One", 1 },
                { "Two", 2 }
            }
        )
}        
3
Kram

名前空間またはクラスを使用して値をネストしないのはなぜですか?不完全かもしれませんが、とてもきれいです。

public static class ParentClass
{
    // here is the "dictionary" class
    public static class FooDictionary
    {
        public const string Key1 = "somevalue";
        public const string Foobar = "fubar";
    }
}

これで、.ParentClass.FooDictionary.Key1などにアクセスできます。

2
Joshua

辞書用の標準の不変のインターフェースはないようです。そのため、残念ながら、ラッパーを作成することが唯一の合理的なオプションのようです。

編集:Marc Gravellは、私が見逃したILookupを見つけました。これにより、少なくとも.ToLookup()で辞書を変換する必要がありますが、少なくとも新しいラッパーの作成を回避できます。

これが特定のシナリオに限定される必要がある場合は、よりビジネスロジック指向のインターフェースを使用する方がよい場合があります。

interface IActiveUserCountProvider
{
    int GetMaxForServer(string serverName);
}
1
Sander

誰もこれに言及していない理由はわかりませんが、C#ではconstを割り当てることができないため、静的な読み取り専用プロパティを使用しています。

例:

public static readonly Dictionary<string, string[]> NewDictionary = new Dictionary<string, string[]>()
        {
            { "Reference1", Array1 },
            { "Reference2", Array2 },
            { "Reference3", Array3 },
            { "Reference4", Array4 },
            { "Reference5", Array5 }
        };
0
Suleman