我可以重写 Dictionary 的 Equals 方法吗?

Can I override Dictionary's Equals method?

提问人:WereElf 提问时间:9/26/2022 最后编辑:M. JustinWereElf 更新时间:11/13/2023 访问量:233

问:

我想用 Dictionary 的 Equals 方法覆盖return d1.Count == d2.Count && !d1.Except(d2).Any();

但我想为所有词典做这件事,而不仅仅是一次只为一个特定的类型。 我目前在我的 ExtensionMethods 类中有一个方法,但它既不是泛型的(使用任何 KeyValuePairs),它实际上也没有覆盖默认的“Equals”方法。public static bool IsEqualTo(this Dictionary<string, byte> d1, Dictionary<string, byte> d2)

有什么方法可以做到这一点,或者我是否坚持使用我目前拥有的东西(也许我至少可以用模板让它更通用)?

C# 字典 重写 相等性

评论

3赞 CodeCaster 9/26/2022
向其传递一个自定义相等比较器。
2赞 Jeroen Mostert 9/26/2022
重写仅与派生类相关。不能更改现有类型的相等规则。根据 CodeCaster,编写一个自定义相等比较器;大多数比较相等的东西都接受比较器(而那些不比较的东西可能无论如何都应该重写)。如果所有其他方法都失败了,您可以拥有 的自定义实现(甚至派生自 ),但当然,如果代码显式实例化或调用 ,则这是没有用的。IDictionary<TKey, TValue>Dictionary<TKey, TValue>Dictionary.ToDictionary

答:

3赞 Dmitry Bychenko 9/26/2022 #1

要使用您自己的自定义 ruls for ,您可以按照 CodeCaster 在注释中的建议实现:EqualityIEqualityComparer<T>

public sealed class DictionaryComparer<K, V> : IEqualityComparer<IDictionary<K, V>> {
  public bool Equals(IDictionary<K, V>? left, IDictionary<K, V>? right) {
    if (ReferenceEquals(left, right))
      return true;
    if (left is null || right is null)
      return false;

    return left.Count == right.Count && !left.Except(right).Any();
  }

  public int GetHashCode(IDictionary<K, V> value) => 
    value is null ? 0 : value.Count; 
}

然后,每当您想比较两个词典时:

Dictionary<int, string> dict1 = ...
Dictionary<int, string> dict2 = ...

if (new DictionaryComparer<int, string>().Equals(dict1, dict2)) {
  //TODO: relevant code here
}

如果喜欢,可以实现扩展方法

public static class DictionaryExtensions {
  public static bool EqualsToDictionary<K, V>(this IDictionary<K, V> left,
                                                   IDictionary<K, V> right) {
    var comparer = new DictionaryComparer<K, V>();

    return compare.Equals(left, right);
  }
}

然后

Dictionary<int, string> dict1 = ...
Dictionary<int, string> dict2 = ...

if (dict1.EqualsToDictionary(dict2)) {
  //TODO: relevant code here
}
1赞 Olivier Jacot-Descombes 9/26/2022 #2

为什么不简单地使你的方法通用呢?IsEqualTo

public static bool IsEqualTo<K, V>(this IDictionary<K, V> d1, IDictionary<K, V> d2)
{
    return d1.Count == d2.Count && !d1.Except(d2).Any();
}

通过扩展而不是,我们可以将扩展方法应用于其他类型的字典,例如 or 等等。IDictionary<TKey,TValue>Dictionary<TKey,TValue>ConcurrentDictionary<TKey,TValue>SortedDictionary<TKey,TValue>

请注意,C# 可以推断泛型类型参数:

var d1 = new Dictionary<string, byte>();
var d2 = new Dictionary<string, byte>();
var s1 = new SortedDictionary<int, string>();
var s2 = new SortedDictionary<int, string>();

// Not necessary to specify the generic type parameters.
bool result1 = d1.IsEqualTo(d2);
bool result2 = s1.IsEqualTo(s2);

评论

1赞 WereElf 9/26/2022
在写这篇文章之前,我没有把它变成通用的,主要是因为我的代码中只有 1 个用例,而且我主要想知道如何做覆盖部分。但是,现在我确实把它变成了通用:P