1

このリンクに示されているソリューションの1つのように、キーごとに複数の値を持つ辞書を作成する方法に関する投稿をここで見ました。

マルチバリューディクショナリ

キーが複数の値を格納できるように、キーの値としてList<>を使用する必要があるようです。

値を追加する場合は、リンクのソリューションで問題ありません。しかし、今の私の問題は、単一のキーから特定の値を削除する方法です。

辞書に値を追加するための次のコードがあります。

private Dictionary<TKey, List<TValue>> mEventDict;
    // this is for initializing the dictionary


public void Subscribe(eVtEvtId inEvent, VtEvtDelegate inCallbackMethod)
    {
        if (mEventDict.ContainsKey(inEvent))
        {
            mEventDict[inEvent].Add(inCallbackMethod);
        }
        else
        {
            mEventDict.Add(inEvent, new List<TValue>() { v });
        }
    }
// this is for adding values to the dictionary.
// if the "key" (inEvent) is not yet present in the dictionary,
// the key will be added first before the value

私の問題は、キーから特定の値を削除することです。私はこのコードを持っています:

public void Unsubscribe(eVtEvtId inEvent, VtEvtDelegate inCallbackMethod)
    {
        try
        {
            mEventDict[inEvent].Remove(inCallbackMethod);
        }

        catch (ArgumentNullException)
        {
            MessageBox.Show("The event is not yet present in the dictionary");
        }
    }

基本的に、私が行ったことは、Add()をRemove()に置き換えることです。これは機能しますか?

また、コードに問題や質問(初期化など)がある場合は、お気軽にお問い合わせください。

アドバイスありがとうございます。

4

3 に答える 3

2

TylerOhlsenの答えは正しい方向への一歩ですが、6つのキールックアップ(Remove、ContainsKey、およびインデクサーの呼び出し)があります。これは、TryGetValueを使用して3つに減らすことができます。

private Dictionary<TKey, List<TValue>> mEventDict;

public void Subscribe(TKey inEvent, TValue inCallbackMethod)
{
    List<TValue> list;

    if (mEventDict.TryGetValue(inEvent, out list))
        list.Add(inCallbackMethod);
    else
        mEventDict.Add(inEvent, new List<TValue> { inCallbackMethod });
}

public bool Unsubscribe(TKey inEvent, TValue inCallbackMethod)
{
    List<TValue> list;

    if (!mEventDict.TryGetValue(inEvent, out list))
        return false;

    bool removed = list.Remove(inCallbackMethod);

    if (list.Count == 0)
        mEventDict.Remove(inEvent);

    return removed;
}

空のリストを削除する必要がない場合:

public bool Unsubscribe(TKey inEvent, TValue inCallbackMethod)
{
    List<TValue> list;

    if (!mEventDict.TryGetValue(inEvent, out list))
        return false;

    return list.Remove(inCallbackMethod);
}

アイテムがリストに含まれていた(したがってリストから削除された)かどうかを報告する必要がない場合は、戻り値のタイプをvoidに変更し、(最初のバージョンでは)removed変数を削除します。

于 2012-10-17T05:09:54.547 に答える
1

それは機能しますか?意図したとおりではありません...

  • メソッドパラメータはジェネリック型である必要があります。
  • List(T).Removeは、ArgumentNullExceptionをスローしません。
  • リストが空になった場合は、辞書をクリーンアップすることをお勧めします。
  • 発信者は、コールバックがサブスクライブ解除されたときにサブスクライブされたかどうかを気にしないかもしれませんが、その情報を持っているので、それを返す方がよいでしょう。この情報は、トラブルシューティング/ログ記録の目的に役立つ可能性があります。

これは私がお勧めするものです...

private Dictionary<TKey, List<TValue>> mEventDict;

public void Subscribe(TKey inEvent, TValue inCallbackMethod)
{
    if (!mEventDict.ContainsKey(inEvent))
        mEventDict.Add(inEvent, new List<TValue>());

    mEventDict[inEvent].Add(inCallbackMethod);
}

public bool Unsubscribe(TKey inEvent, TValue inCallbackMethod)
{
    if (!mEventDict.ContainsKey(inEvent))
        return false;

    bool removed = mEventDict[inEvent].Remove(inCallbackMethod);

    if (mEventDict[inEvent].Count == 0)
        mEventDict.Remove(inEvent);

    return removed;
}

注:私はこのコードをテストしていないので、試してみてください。また、このコードはスレッドセーフではありません。

于 2012-10-17T04:01:09.393 に答える
0

@phoog-したがって、Unsubscribeメソッドを。のままにしておきvoidます。あなたのコードを変更した後、これは私が思いついたものです...

public void Unsubscribe(TKey inEvent, TValue inCallbackMethod)
{
    List<TValue> list;

    bool mRemoved = false.

    if (mEventDict.TryGetValue(inEvent, out list))
    {
        list.Remove(inCallbackMethod);
        mRemoved = true;
    }
}

listRemoved変数は必要ですか?inCallbackMethodしかし、繰り返しになりますが、リストにが見つからない場合は何も起こらないと思います。

于 2012-10-17T22:59:15.500 に答える