C# - 使用自定义键定义hashset

Mah*_*kia 11 .net c# dictionary hashset

我在C#中使用HashSetand Dictionary来实现Graph结构.HashSet当HashSet键是自定义类时,我遇到元素唯一性的问题.我在这里:

public class Point
{
    public int x { get; set; }
    public int y { get; set; }
}

public class Vertex
{
    public Vertex(Point point)
    {
        VertexLabel = point;
    }

    public Point VertexLabel { get; private set; }
}

public class Edge
{
    public Edge(Vertex to, Vertex from, double weight)
    {
        FromVertex = from;
        ToVertex = to;
        Weight = weight;
    }

    public Vertex FromVertex { get; private set; }
    public Vertex ToVertex { get; private set; }
    public double Weight { get; private set; }
}

public class Graph
{
    public Graph()
    {
        _Vertexes = new HashSet<Vertex>();
        _VertexEdgeMapping = new Dictionary<Vertex, LinkedList<Edge>>();
    }
    private HashSet<Vertex> _Vertexes;
    private Dictionary<Vertex, LinkedList<Edge>> _VertexEdgeMapping;
}
Run Code Online (Sandbox Code Playgroud)

问题是当我有相同的顶点并且我想将它们添加到图形时,它们会被复制.如何定义一种HashSet能够理解顶点唯一性的方法?

Jon*_*eet 27

选项:

  • 覆盖Equals和GetHashCode在Vertex(可能Point为简单起见),很可能实现IEquatable<T>,当您去
  • 创建自己的实现IEqualityComparer<Vertex>并将其传递给.的构造函数HashSet<Vertex>

第一个选项可能是最简单的,但我强烈建议您Point首先使用不可变类型:可变类型(或包含可变类型的类型)不能生成好的哈希键.我也许可以做到struct:

public struct Point : IEquatable<Point>
{
    private readonly int x, y;

    public int X { get { return x; } }
    public int Y { get { return y; } }

    public Point(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public override int GetHashCode()
    {
        return 31 * x + 17 * y; // Or something like that
    }

    public override bool Equals(object obj)
    {
        return obj is Point && Equals((Point) obj);
    }

    public bool Equals(Point p)
    {
        return x == p.x && y == p.y;
    }

    // TODO: Consider overloading the == and != operators
}
Run Code Online (Sandbox Code Playgroud)

......然后覆盖GetHashCode,并Equals贯彻IEquatable<>在Vertex太,如

// Note: sealed to avoid oddities around equality and inheritance
public sealed class Vertex : IEquatable<Vertex>
{
    public Vertex(Point point)
    {
        VertexLabel = point;
    }

    public Point VertexLabel { get; private set; }

    public override int GetHashCode()
    {
        return VertexLabel.GetHashCode();
    }

    public override bool Equals(object obj)
    { 
        return Equals(obj as Vertex);
    }

    public bool Equals(Vertex vertex)
    {
        return vertex != null && vertex.VertexLabel.Equals(VertexLabel);
    }
}      
Run Code Online (Sandbox Code Playgroud)

  • 对于那些想知道为什么他将`x`和`y`乘以常数的人来说,它是为了帮助更多地分配哈希码.这使得"X = 12"和"Y = 13"的点具有与具有"X = 13"和"Y = 12"的点不同的哈希码. (6认同)
  • 我想你错过了`public virtual bool Equals(object obj)`上的`override`关键字 (2认同)