创建了一个图的一个边类
struct Edge : IEqualityComparer<Edge>
{
private Vertex v_startPoint;
private Vertex v_endPoint;}
现在希望
Vertex anve = new Vertex(81.884214, 49.504255);
Vertex ve = new Vertex(85.693406, 49.773224);
现在我要 new Edge(anve,ve) 和 new Edge(ve,anve)
表示的是同一个东西, 有什么办法吗?
表面的意思就是你创建两个点之间的边 不论顶点的先后顺序 都是指的同一个边
------解决思路----------------------
图的一般实现有QuickGraph可以直接用。
如果确实想自己写,这个需求就是实现标准的Equals模式,包括override Equals、GetHashCode方法,实现==、!=两个运算符,实现IEquatable<T>也就是强类型的Equals方法,一共5个方法。其中Equals、==、!=三个方法是标准写法,自己实际需要实现的就是泛型Equals和GetHashCode两个方法。
想要Edge支持相等性判断,Vertex也必须支持,代码如下(ReSharper可以辅助实现Equals模式,自己稍微改改):
public struct Vertex : IEquatable<Vertex>
{
public readonly float x;
public readonly float y;
public Vertex(float x, float y)
{
this.x = x;
this.y = y;
}
public bool Equals(Vertex other)
{
return x.Equals(other.x) && y.Equals(other.y);
}
public override int GetHashCode()
{
unchecked
{
return (x.GetHashCode()*397) ^ y.GetHashCode();
}
}
public static bool operator ==(Vertex left, Vertex right)
{
return left.Equals(right);
}
public static bool operator !=(Vertex left, Vertex right)
{
return !left.Equals(right);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
return false;
return obj is Vertex && Equals((Vertex)obj);
}
}
public struct Edge : IEquatable<Edge>
{
public readonly Vertex start;
public readonly Vertex end;
public Edge(Vertex start, Vertex end)
{
this.start = start;
this.end = end;
}
public bool Equals(Edge other)
{
// 同向反向都认为相等
return (start.Equals(other.start) && end.Equals(other.end))
------解决思路----------------------
(start.Equals(other.end) && end.Equals(other.start));
}
public override int GetHashCode()
{
unchecked
{
// 同向反向的hash结果相同
return start.GetHashCode() ^ end.GetHashCode();
}
}
public static bool operator ==(Edge left, Edge right)
{
return left.Equals(right);
}
public static bool operator !=(Edge left, Edge right)
{
return !left.Equals(right);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
return false;
return obj is Edge && Equals((Edge)obj);
}
}
------解决思路----------------------
楼上是个标准做法,再给个另类做法,思路很简单,对Edge的构造函数动一点手脚,让顶点始终按照一种方式保存,这样别的代码都不用动了。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
struct Vertex
{
public double X { get; private set; }
public double Y { get; private set; }
public Vertex(double x, double y) : this()
{
X = x;
Y = y;
}
}
struct Edge : IEqualityComparer<Edge>
{
public Vertex StartPoint { get; private set; } //在这里,我们让顶点只读,否则在顶点赋值的时候,需要重新判断
public Vertex EndPoint { get; private set; }
public Edge(Vertex start, Vertex end) : this()
{
// 始终让start存放x大的,如果x一样大,存放y大的。
if (start.X > end.X
------解决思路----------------------
(start.X == end.X && start.Y > end.Y))
{
StartPoint = start; EndPoint = end;
}
else
{
StartPoint = end; EndPoint = start;
}
}
public bool Equals(Edge x, Edge y)
{
return x.StartPoint.Equals(y.StartPoint) && x.EndPoint.Equals(y.EndPoint);
}
public int GetHashCode(Edge obj)
{
return obj.StartPoint.GetHashCode() + obj.EndPoint.GetHashCode();
}
}
class Program
{
static void Main(string[] args)
{
Edge ed1 = new Edge(new Vertex(1.234, 4.321), new Vertex(5.678, 8.765));
Edge ed2 = new Edge(new Vertex(1.234, 4.321), new Vertex(5.678, 8.765));
Console.WriteLine(ed1.Equals(ed1, ed2));
ed2 = new Edge(new Vertex(5.678, 8.765), new Vertex(1.234, 4.321));
Console.WriteLine(ed1.Equals(ed1, ed2));
}
}
}