4

SO にも同様の質問がありましたが、どれも私の質問に答えませんでした。

翻訳用の二次元辞書が欲しいです。このようなもの:

Dictionary["DE"][TranslationKeys.Title] = "Title in German";
Dictionary["DE"][TranslationKeys.SubTitle] = "Subtitle in German";
Dictionary["PL"][TranslationKeys.Title] = "Title in Polish";
Dictionary["PL"][TranslationKeys.SubTitle] = "Subtitle in Polish";
Dictionary["EN"][TranslationKeys.Title] = "Title in English";
Dictionary["EN"][TranslationKeys.SubTitle] = "Subtitle in English";

のような伝統的な辞書を使用すれば、これは問題ありませんDictionary<string,Dictionary<TranslationKeys,string>>

しかし、次のような「醜い」方法で初期化したくありません。

Dictionary = new Dictionary<string,Dictionary<TranslationKeys,string>>(){
                {"PL",new Dictionary<TranslationKeys,string>(){{TranslationKeys.SubTitle,"Subtitle in Polish"}}}
            };

しかし、このように:

Dictionary["PL"][TranslationKeys.SubTitle] = "Subtitle in Polish";

そこで私は、彼が値を取得したかどうかを判断する「インテリジェントな」多次元辞書を実装しようとしました。これまでに行ったことは、ディクショナリと特別なインデクサーを使用する新しいジェネリック クラスです。

public class TranslateDictionary<TKey, TValue> where TValue : new()
{
    private Dictionary<TKey, TValue> Dictionary;
    public TValue this[TKey lang]
    {
        get
        {
            if (!Dictionary.ContainsKey(lang))
            {
                TValue obj = new TValue();
                Dictionary.Add(lang, new TValue());
            }
            return Dictionary[lang];
        }
        set
        {
            Dictionary[lang] = value;
        }
    }
}

しかし、今は立ち往生しています...ジェネリック型のTranslateDictionaryで文字列を使用しているため、このエラーが発生します:

エラー 2 'string' は、ジェネリック型またはメソッド 'Resources.TranslateDictionary' でパラメーター 'TValue' として使用するために、パブリック パラメーターなしのコンストラクターを持つ非抽象型である必要があります

ただし、コンパイラは次のような初期化について不平を言いません。

Dictionary["EN"][TranslationKeys.Title] = "Title in English";

私の問題を解決するために、私が認識していない Dictionary の代わりに他のタイプのコレクションを使用する必要がありますか?

4

1 に答える 1

4

やったよ。インデクサーを少し変更する必要がありました。これを機能させる方法は次のとおりです。

public class TranslateDictionary<TKey, TValue>
{
    private Dictionary<TKey, TValue> Dictionary = new Dictionary<TKey,TValue>();
    public TValue this[TKey lang]
    {
        get
        {
            if (!Dictionary.ContainsKey(lang))
            {
                Dictionary.Add(lang, Activator.CreateInstance<TValue>());
            }
            return Dictionary[lang];
        }
        set
        {
            Dictionary[lang] = value;
        }
    }
}

今、あなたが持っているとき

TranslateDictionary<string, TranslateDictionary<TranslationKeys, string>> Dictionary { get; set; }

辞書のインスタンスを作成するだけです。

Dictionary = new TranslateDictionary<string, TranslateDictionary<TranslationKeys, string>>();

そして、次のように要素を自由に初期化できます。

Dictionary["PL"][TranslationKeys.SubTitle] = "SubTitle in Polish";
Dictionary["EN"][TranslationKeys.SubTitle] = "SubTitle in English";
Dictionary["DE"][TranslationKeys.SubTitle] = "SubTitle in German";

値を読み取ろうとするたびに内部辞書にキーが含まれているかどうかを確認するため、このアプローチは通常の辞書よりも遅いかもしれませんが、少なくとも「よりクリーンな」方法で要素を割り当てることができます。

更新 TranslateDictionary を少しアップグレードしました。ブール値のプロパティ「初期化済み」を追加しました。初期化後、この値を「true」に設定すると、辞書に値が存在するかどうかを確認する必要がなくなります。そして、通常の Dictioanry タイプのように動作します。

public class TranslateDictionary<TKey, TValue>
{
    public bool Initialized { get; set; }
    private Dictionary<TKey, TValue> Dictionary = new Dictionary<TKey,TValue>();
    public TValue this[TKey lang]
    {
        get
        {
            if (!Initialized)
            {
                if (!Dictionary.ContainsKey(lang))
                {
                    Dictionary.Add(lang, Activator.CreateInstance<TValue>());
                }
            }
            return Dictionary[lang];
        }
        set
        {
            Dictionary[lang] = value;
        }
    }
}
于 2013-06-15T08:29:29.427 に答える