【问题标题】:Implement a custom hashcode on a third party class在第三方类上实现自定义哈希码
【发布时间】:2020-02-08 11:53:15
【问题描述】:

我在 VisualStudio C# 项目中使用来自第三方的 Line 类(无法访问源代码) 我的代码正在生成数百/数千个包含重复项的行对象,我需要将它们存储在某种集合(List、HashSet)中以进行进一步处理(在屏幕上绘图)。 Line 类具有 Point 类型的 StartPoint 和 EndPoint 属性等。 出于我需要做的目的,线方向无关紧要,如果起点和终点相同,则两个 Line 对象是相同的。 然而,我使用的类的行为不同,两个 Line 对象被认为是唯一的,即使它们具有相同的起点/终点。 (GetHashCode 返回不同的值) 问题是 - 如何为第三方类实现自定义 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();

timer.Start();

var 结果 = new HashSet(new LineComparer());

GenerateAndStore20000Lines();

timer.Stop(); Ed.WriteMessage($"\n生成的 {result.Count} 行,带有哈希集的时间:{timer.ElapsedMilliseconds}");

返回结果;

结果: * 使用 HashSet 的时间:1302 * 使用 HashSet 的时间:1328 * 使用 HashSet 的时间:1314 * 使用 HashSet 的时间:1311 * 使用 HashSet 的时间:1303

带有列表的代码:

var timer = new Stopwatch(); 计时器.Start();

var 结果 = new List();

GenerateAndStore20000Lines();

timer.Stop(); Ed.WriteMessage($"\n生成的 {result.Count} 行,使用 List 的时间:{timer.ElapsedMilliseconds}");

return result.Distinct(new LineComparer());

结果:

  • 生成 20002 行,List 时间:26
  • 生成 20002 行,List 时间:11
  • 生成 20002 行,List 时间:14
  • 生成 20002 行,List 时间:12
  • 生成 20002 行,列表时间:12

(抱歉格式不好,但这个界面让我发疯......放弃)

【问题讨论】:

标签: c# unique distinct hashcode gethashcode


【解决方案1】:

将重载与 IEqualityComparer 一起使用(您必须实现)。

请参阅this 以获取HashSet

我想,你的意思是Enumerable.Distinct。使用this

【讨论】:

    【解决方案2】:

    我只是在扩展 @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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-18
      相关资源
      最近更新 更多