键的任意元组字典(不包括在类中)

时间:2011-10-10 02:47:57

标签: c# dictionary

在C#中,Dictionary类只使用一个键并将其映射到单个值。我正在寻找类似的东西,我可以在其中传递一个有序的元组并获得单个值 - 没有将它包装在一个类中。

这是我想要的一个非常假设的例子(使用按钮,而不是某些2D地图图块)。目前,我可以这样做:

Dictionary<int, Button> buttons = new Dictionary<int, Button>();

如果我想使用每个按钮的坐标作为键,我可以这样做:

Dictionary<Point, Button> buttons = new Dictionary<Point, Button>();
buttons[new Point(b.X, b.Y)] = b;

我想做的是这个

Dictionary<int, int, Button> buttons = new Dictionary<int, int, Button>();
buttons[b.X, b.Y] = b;

同样,这是一个简单的案例,有一个已知的解决方法。但我觉得很烦人,我必须创建一个新的占位符类(struct?),其中包含我想用作关键字的每组参数。

这有可能吗?

3 个答案:

答案 0 :(得分:5)

public class TupleDictionary<T1, T2, TValue> : Dictionary<Tuple<T1,T2>,TValue>
{
    public TValue this[T1 t1, T2 t2]
    {
        get { return this[new Tuple<T1, T2>(t1, t2)]; }
        set { this[new Tuple<T1, T2>(t1,t2)] = value; }
    }

    public void Add(T1 t1, T2 t2, TValue value)
    {
        Add(new Tuple<T1, T2>(t1, t2), value);
    }

    public void Remove(T1 t1, T2 t2)
    {
        Remove(new Tuple<T1, T2>(t1, t2));
    }

    public bool ContainsKey(T1 t1, T2 t2)
    {
        return ContainsKey(new Tuple<T1, T2>(t1, t2));
    }

    public bool TryGetValue(T1 t1, T2 t2, out TValue value)
    {
        return TryGetValue(new Tuple<T1, T2>(t1, t2), out value);
    }
}

答案 1 :(得分:2)

在.Net 4中,您可以使用元组作为字典键

Dictionary<Tuple<int, int>, Button> buttons = new Dictionary<Tuple<int, int>, Button>();
buttons[new Tuple<int,int>(b.X, b.Y)] = b;

答案 2 :(得分:2)

这是扩展方法可能有用的情况。

我编写了一堆字典扩展方法,允许GetOrAddGetOrDefault等函数在标准字典上工作,这有助于减少检查项目是否已存在于字典中的所有噪音

同样,您可以使用扩展方法扩展嵌套字典。

所以,也许你可以编写这样的代码:

var buttons = new Dictionary<int, Dictionary<int, Button>>();

buttons.Add(b.X, b.Y, b);
buttons.AddOrReplace(b1.X, b1.Y, b1);

我的Add方法如下所示:

    public static void Add<K1, K2, V>(
            this IDictionary<K1, Dictionary<K2, V>> @this,
            K1 key1,
            K2 key2,
            V value)
    {
        if (@this == null) { throw new ArgumentNullException("@this"); }
        if (key1 == null) { throw new ArgumentNullException("key1"); }
        if (key2 == null) { throw new ArgumentNullException("key2"); }
        if (!@this.ContainsKey(key1))
        {
            @this[key1] = new Dictionary<K2, V>();
        }
        @this[key1][key2] = value;
    }

这种方法很不错,因为您仍在使用标准.NET词典,但只需要相对较小的语法差异即可获得您所使用的功能。

另一种方法是定义自己的类字典类。像这样:

public class TupleDictionary<K1, K2, V>
{
    public void Add(K1 key1, K2 key2, V value);
    public bool ContainsKey(K1 key1, K2 key2);
    public bool Remove(K1 key1, K2 key2);

    public Dictionary<K2, V> this[K1 key1] { get; }
}

然后,因为this索引属性将“获取或添加”内部词典,您可以像这样编写代码:

var td = new TupleDictionary<int, int, Button>();

td[b.X][b.Y] = b;

从语法上讲,它看起来与您的示例代码相同,但您需要编写大量代码才能获得此特定语法。

我认为使用嵌套字典的扩展方法是可行的方法。