【发布时间】: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
(抱歉格式不好,但这个界面让我发疯......放弃)
【问题讨论】:
-
您只需要一个自定义的
IEqualityComparer。更棘手的部分是 GetHashCode()。如果您查看base implementation of Point.GetHashCode()(PointF 有一个不同的,与它的基类ValueType相同),您很快就会发现您不能依赖它们中的任何一个。不同的 Point/PoinF 结构不断获得相同的 Hash。因此,您不能只取 Line 对象的两个 Point 值并使用默认实现(我们称之为)对它们进行哈希处理。 -
请参阅 Eric Lippert:Guidelines and rules for GetHashCode、Hans Passant:How does native implementation of ValueType.GetHashCode work? 和 Jon Skeet:What is the best algorithm for overriding GetHashCode?。
标签: c# unique distinct hashcode gethashcode