簡體   English   中英

在第三方 class 上實現自定義哈希碼

[英]Implement a custom hashcode on a third party class

我在 VisualStudio C# 項目中使用來自第三方的 Line class(無法訪問源代碼) 我的代碼正在生成數百/數千個包含重復項的行對象,我需要將它們存儲在某種集合中(List、HashSet)用於進一步處理(在屏幕上繪圖)。 線 class 具有 Point 類型的 StartPoint 和 EndPoint 屬性等。 出於我需要做的目的,線方向無關緊要,如果起點和終點相同,則兩個 Line 對象是相同的。 然而,我使用的 class 的行為不同,兩個 Line 對象被認為是唯一的,即使它們具有相同的起點/終點。 (GetHashCode 返回不同的值) 問題是 - 如何為第三方 class 實現自定義 IComparer 或 GetHashCode 例程,以便能夠使用 HashSet 結構或 List.Distinct() 功能?

謝謝 Ilian 和 Hasan,如果你不介意的話,那就是訣竅快速跟進問題:我不確定是使用 List 還是 HashSet 來保存我的數據,所以我嘗試了兩者並計時。 結果表明,一個比另一個慢幾個數量級。 關於發生了什么的任何見解?

class LineComparer : IEqualityComparer<Line>
{
    public bool Equals(Line l1, Line l2)
    {
        if (l1.EndPoint == l2.EndPoint && l1.StartPoint == l2.StartPoint) return true;
        if (l1.EndPoint == l2.StartPoint && l1.StartPoint == l2.EndPoint) return true;
        return false;
    }
    public int GetHashCode(Line line) => line.StartPoint.GetHashCode() ^ line.EndPoint.GetHashCode();
}

這是我的 HashSet 代碼:

var timer = new Stopwatch();

計時器.Start();

var result = new HashSet(new LineComparer());

GenerateAndStore20000Lines();

計時器.停止(); Ed.WriteMessage($"\n生成的 {result.Count} 行,使用哈希集的時間:{timer.ElapsedMilliseconds}");

返回結果;

結果: * 使用 HashSet 的時間:1302 * 使用 HashSet 的時間:1328 * 使用 HashSet 的時間:1314 * 使用 HashSet 的時間:1311 * 使用 HashSet 的時間:1303

帶有列表的代碼:

var timer = new 秒表(); 計時器.Start();

var 結果 = 新列表();

GenerateAndStore20000Lines();

計時器.停止(); Ed.WriteMessage($"\n生成的 {result.Count} 行,列表時間:{timer.ElapsedMilliseconds}");

返回結果.Distinct(new LineComparer());

結果:

  • 生成 20002 行,列表時間:26
  • 生成 20002 行,列表時間:11
  • 生成 20002 行,列表時間:14
  • 生成 20002 行,列表時間:12
  • 生成 20002 行,列表時間:12

(抱歉格式不好,但這個界面讓我發瘋......放棄)

將重載與IEqualityComparer一起使用(您必須實現)。

HashSet

我假設,你的意思是Enumerable.Distinct 使用這個

我只是在擴展@Ilian的答案。 試圖盡可能多地發表評論,所以我相信代碼進行談話會更好:)

// Mock 3rd Party point
public class ThirdPartyPoint {

}

// Mock 3rd party line
public class ThirdPartyLine {

    public ThirdPartyPoint StartPoint { get; set; }
    public ThirdPartyPoint EndPoint { get; set; }

}

// This class implements IEqualityComparer<ThirdPartyLine>, which compares
// ThirdPartyLine's equality. THis class will be passed as a ctor arument to HashSet<T>
public class CompareLines : IEqualityComparer<ThirdPartyLine> {

    public bool Equals(ThirdPartyLine x, ThirdPartyLine y) {
        // Here check for the equality of the start and end points.
        // I asuumed the following but do not know how the eaulity is implemented in your library.
        return x.EndPoint == y.EndPoint && x.StartPoint == y.StartPoint;
    }

    public int GetHashCode(ThirdPartyLine obj) {
        // Implement an algortihm which must return same hashcode for objects considered the same.
        // I am not sure about the Point class hashcode but I am jsut assuming the following.
        return obj.StartPoint.GetHashCode() ^ obj.EndPoint.GetHashCode();
    }

}


private static void Main(string[] args) {
    // Hashset to hold lines
    var hashSet = new HashSet<ThirdPartyLine>(new Compare());
    // start point
    var starPoint = new ThirdPartyPoint();
    // end point
    var endPoint = new ThirdPartyPoint();

    // Lines with same start and end points
    var line1 = new ThirdPartyLine {
        StartPoint = starPoint,
        EndPoint = endPoint
    };

    var line2 = new ThirdPartyLine {
        StartPoint = starPoint,
        EndPoint = endPoint
    };


    // Check count first
    hashSet.Add(line1);
    var count = hashSet.Count;

    // Check count second, still 1
    hashSet.Add(line2);
    count = hashSet.Count;
}

暫無
暫無

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

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