簡體   English   中英

如何實現多個 GetHashCode 方法?

[英]How to implement multiple GetHashCode methods?

我有一個定義復合鍵的接口:

public interface IKey : IEquatable<IKey>
{
    public bool KeyPart1 { get; }
    public uint KeyPart2 { get; }
    int GetHashCode(); // never gets called
}

我有一個對象(帶有 ID),我想向其中添加復合鍵接口:

public class MyObject: IEquatable<MyObject>, IKey
{
    public MyObject(int i, (bool keyPart1, uint keyPart2) key) {
    {
        Id=i;
        KeyPart1 = key.keyPart1;
        KeyPart2 = key.keyPart2;
    }
    
    public int Id { get; }
    public bool KeyPart1 { get; }
    public uint KeyPart2 { get; }

    public bool Equals(MyObject other) => this.Id == other.Id;

    public override bool Equals(object other) => other is MyObject o && Equals(o);
    public override int GetHashCode() => Id.GetHashCode();

    bool IEquatable<IKey>.Equals(IKey other) => this.KeyPart1 == other.KeyPart1
                                                && this.KeyPart2 == other.KeyPart2;
    int IKey.GetHashCode() => (KeyPart1, KeyPart2).GetHashCode(); // never gets called
}

但是,當擁有這些對象的列表並嘗試使用界面對它們進行分組時,分組失敗:

var one = new MyObject(1, (true, 1));
var two = new MyObject(2, (true, 1));
var three = new MyObject(1, (false, 0));
var items = new[] { one, two, three };

var byId = items.GroupBy(i => i);
// result: { [one, three] }, { [two] } -- as expected

var byKey = items.GroupBy<MyObject, IKey>(i => i as IKey);

// result: { [one, two, three] } // not grouped (by 'id' or 'key')
// expected: { [one, two] }, { [three] }

我希望byId將按Id屬性分組項目,而byKey將按Key屬性分組項目。

但是, byKey根本沒有分組。 似乎總是使用覆蓋GetHashCode()方法而不是顯式實現的接口方法。

是否有可能實現這樣的事情,其中​​被分組的項目的類型決定了要使用的哈希方法(避免EqualityComparer )?

在將IEnumerable<IKey>對象傳遞給另一個需要IEnumerable<IKey>方法時,我注意到了這個問題。 我有幾種不同的類型實現了IKey ,那些具有現有GetHashCode()方法的類型不起作用,而其他類型則起作用。

請注意這里的對象已被簡化,我無法輕易更改接口(例如使用ValueTuple代替)。

等式中使用的GetHashCode()是:

  • 如果沒有提供相等比較器,則通過object.GetHashCode()定義的
  • IEqualityComparer<T>.GetHashCode(T) ,如果提供了相等比較器

在您自己的接口上添加您自己的GetHashCode()方法沒有任何作用,並且永遠不會使用它,因為它不是框架/庫代碼知道的 API 的一部分。

所以,我會忘記IKey.GetHashCode()和其中一個(或兩者):

  • 使MyObject.GetHashCode()提供您需要的功能,或
  • MyObject實例單獨提供一個自定義的相等比較器

對於第二個選項,有接受IEqualityComparer<TKey>GroupBy重載。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM