添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

What wizardry is in that System.Drawing.Point class that makes it so much faster than my simple struct?

It's quite a bit faster. I'm getting 1-5ms on Point class and 2000ms or more on my struct.

Looking at the Points.cs source , I'm not skilled enough to spot what is doing it. I made an attempt at implementing IEquatable (probably incorrectly) and couldn't make any gains.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
class Program
    static void Main(string[] args)
        Stopwatch sw = new Stopwatch();
        int elementsInSets = 10000;
        int lookupCount = 10000;
        // Point struct from System.Drawing
        HashSet<Point> myPoints = new HashSet<Point>();
        for (int i = 0; i < elementsInSets; i++)
            myPoints.Add(new Point(i, i));
        // My simple struct
        HashSet<P> myPoints2 = new HashSet<P>();
        for (int i = 0; i < elementsInSets; i++)
            myPoints2.Add(new P(i, i));
        sw.Start();
        for (int j = 0; j < lookupCount; j++)
            if (myPoints2.Contains(new P(j, j)))
                //found
        Console.WriteLine("simple P  " + sw.ElapsedMilliseconds + "ms");
        sw.Restart();
        for (int j = 0; j < lookupCount; j++)
            if (myPoints.Contains(new Point(j, j)))
                // found
        Console.WriteLine("Point " + sw.ElapsedMilliseconds + "ms");     
public struct P
    int x;
    int y;
    public P(int xCoord, int yCoord)
        x = xCoord;
        y = yCoord;
                The reference source you are reading is almost certainly not the 'real' code that you are looking for.
– not my real name
                Apr 22, 2020 at 15:00
                The efficiency of HashSet critically depends on the quality of the object's GetHashCode() implementation.  Point has one, yours doesn't.  Notes on creating a better one are here.  The PointComparer in that snippet makes it too fast to measure (0 msec).  Which exposes a problem with Point.GetHashCode(), it doesn't work very well when x==y.
– Hans Passant
                Apr 22, 2020 at 15:11

That's due to no override for GetHashCode (you should also override Equals) as in the Point source. They do it this way:

public override bool Equals(object obj) {
    if (!(obj is Point)) return false;
    Point comp = (Point)obj;
    // Note value types can't have derived classes, so we don't need 
    // to check the types of the objects here.  -- Microsoft, 2/21/2001
    return comp.X == this.X && comp.Y == this.Y;
public override int GetHashCode() {
    return unchecked(x ^ y);

If your implementation was the same you should see similar performance.

Thank you very much folks. That was indeed it. Both this and Martin's answer were spot on. I'm giving this answer the check mark only because Zer0 types faster. – user9630231 Apr 22, 2020 at 19:53

While a struct provides a default implementation for Equals and GetHashCode they have bad performance as they use reflection. Instead you should provide your own implementation. While you don't have to implement IEquatable<Point> I think it's worthwhile:

readonly struct Point : IEquatable<Point>
    public Point(int x, int y)
        X = x;
        Y = y;
    public int X { get; }
    public int Y { get; }
    public bool Equals(Point other) => X == other.X && Y == other.Y;
    public override bool Equals(object obj) => obj is Point point && Equals(point);
    public override int GetHashCode() => HashCode.Combine(X, Y);

I did a casual benchmark using your code and the performance of this code is similar to System.Drawing.Point or perhaps slightly slower but not thousands of times slower like the naïve approach.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.