繁体   English   中英

如何使用 ValueTuples 创建一个不区分大小写的通用多键字典?

[英]How can I create a generic case-insensitive multi-key dictionary using ValueTuples?

我知道我可以使用System.ValueTuple键(基于此答案)定义字典,如下所示:

var multiKeyDictionary = new Dictionary<(int key1, string key2), object>()
{
    {(1, "test"), new object() }
};

但是,我希望ValueTuple中存在的任何string值都被视为不区分大小写,使用IEqualityComparer或类似的字典访问习惯用语,类似于此处规定的内容。

到目前为止我想到的解决方案是:

class InsensitiveValueTupleDictionary
{
    private Dictionary<(int key1, string key2), object> _multiKeyDictionary = new Dictionary<(int key1, string key2), object>();

    public void Add((int key1, string key2) key, object value)
    {
        _multiKeyDictionary.Add((key.key1, key.key2.ToLower()), value);
    }

    public bool ContainsKey((int key1, string key2) key)
    {
        return _multiKeyDictionary.ContainsKey((key.key1, key.key2.ToLower()));
    }

    // ... and so on
}

这两种策略都需要为ValueTuple的每个唯一组合设置代码,例如(int, string) , (string, int) , (string, string, int)等等。

是否有另一种方法允许任意ValueTuple组合不区分大小写的键相等?

您正在使用元组将自己画到那个角落。 元组旨在表示一袋值,而不是实体。

您可以以元组友好的方式实现自己的键类型:

public struct Key : IEquatable<Key>
{
    private readonly int hashCode;

    public Key(int key1, string key2)
    {
        this.Key1 = key1;
        this.Key2 = key2;
        this.hashCode = HashCode.Combine(key1, StringComparer.OrdinalIgnoreCase.GetHashCode(Key2));
    }

    public int Key1 { get; }
    public string Key2 { get; }

    public bool Equals(Key other)
        => this.hashCode == other.hashCode
            && this.Key1 == other.Key1
            && string.Equals(this.Key2, other.Key2, StringComparison.OrdinalIgnoreCase);

    public override bool Equals(object obj)
        => obj is Key key && this.Equals(key);

    public override int GetHashCode() => this.hashCode;
    
    public static implicit operator (int key1, string key2)(Key key)
        => (key1: key.Key1, key2: key.Key2);
    
    public static implicit operator Key((int key1, string key2) key)
        => new Key(key.key1, key.key2);
    
    public void Deconstruct(out int key1, out string key2)
        => (key1, key2) = (this.Key1, this.Key2);
}

您甚至可以将它与元组或“喜欢”元组一起使用:

var key = new Key(1, "one");
var (k1, k2) = key;
(int key1, string key2) t = key;
t.key1 = 2;
t.key2 = "two";
key = t;

如果您真的想保留元组,请定义自己的比较器:

public class MyTupleComparer : IEqualityComparer<(int key1, string key2)>
{
    public bool Equals((int key1, string key2) x, (int key1, string key2) y)
        => x.key1 == y.key1
            && string.Equals(x.key2, y.key2, StringComparison.OrdinalIgnoreCase);

    public int GetHashCode((int key1, string key2) obj)
    => HashCode.Combine(obj.key1, StringComparer.OrdinalIgnoreCase.GetHashCode(obj.key2));
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM