C#で定数辞書を作成する
-
06-07-2019 - |
質問
string
sからint
sへの定数(実行時に変更しない)マッピングを作成する最も効率的な方法は何ですか?
const辞書、しかしそれはうまくいかなかった。
不変ラッパー適切なセマンティクスを使用しますが、それでも完全に正しいとは思えません。
尋ねた人のために、 IDataErrorInfo を生成されたクラスで使用し、columnNameで記述子の配列を検索する方法を探しています。
スイッチが文字列を受け入れることを認識していなかったので(テスト時のタイプミス!)、それを使用します。ありがとう!
解決
実際にコンパイル時に生成される定数辞書をC#で作成するのは、簡単な作業ではありません。実際、ここでの答えはどれもそれを実際に達成しません。
要件を満たすソリューションが1つありますが、必ずしも良いものではありません。 C#仕様によると、switch-caseテーブルは定数ハッシュジャンプテーブルにコンパイルされることに注意してください。つまり、これらは定数辞書であり、一連のif-elseステートメントではありません。したがって、次のようなswitch-caseステートメントを検討してください。
switch (myString)
{
case "cat": return 0;
case "dog": return 1;
case "elephant": return 3;
}
これはまさにあなたが望むものです。そして、はい、私は知っている、それはいです。
他のヒント
現在のフレームワークには、不変のコレクションがほとんどありません。 .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();
enum Constants
{
Abc = 1,
Def = 2,
Ghi = 3
}
...
int i = (int)Enum.Parse(typeof(Constants), "Def");
これは、<!> quot; CONST Dictionary <!> quot;:
に最も近いものです。public static int GetValueByName(string name)
{
switch (name)
{
case "bob": return 1;
case "billy": return 2;
default: return -1;
}
}
コンパイラは、コードを可能な限りクリーンにビルドするのに十分なほどスマートです。
4.5+ Frameworkを使用している場合、ReadOnlyDictionary(リストの場合はReadOnly Collection)を使用して、読み取り専用のマッピング/定数を実行します。以下の方法で実装されています。
static class SomeClass
{
static readonly ReadOnlyDictionary<string,int> SOME_MAPPING
= new ReadOnlyDictionary<string,int>(
new Dictionary<string,int>()
{
{ "One", 1 },
{ "Two", 2 }
}
)
}
名前空間またはクラスを使用して値をネストしないのはなぜですか?不完全かもしれませんが、非常にきれいです。
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などにアクセスできるようになりました。
辞書用の標準の不変のインターフェースはないようですので、残念ながら、ラッパーを作成することが唯一の合理的なオプションのようです。
編集:Marc Gravellは見落としたILookupを見つけました。これにより、少なくとも.ToLookup()で辞書を変換する必要がありますが、少なくとも新しいラッパーの作成を回避できます。
これが特定のシナリオに制限される必要がある場合、よりビジネスロジック指向のインターフェースを使用する方がよい場合があります。
interface IActiveUserCountProvider
{
int GetMaxForServer(string serverName);
}
理由:
public class MyClass
{
private Dictionary<string, int> _myCollection = new Dictionary<string, int>() { { "A", 1 }, { "B", 2 }, { "C", 3 } };
public IEnumerable<KeyValuePair<string,int>> MyCollection
{
get { return _myCollection.AsEnumerable<KeyValuePair<string, int>>(); }
}
}