我有个问题。我创建了一个这样的字典:
var TriangleRegistry = new Dictionary<string, TriangleRegistryObject>();
像这样的课程:
class TriangleRegistryObject
{
public double x1 { get; set; }
public double y1 { get; set; }
public double x2 { get; set; }
public double y2 { get; set; }
public double x3 { get; set; }
public double y3 { get; set; }
public bool Selected { get; set; }
}
字典中充满了三角形的坐标。现在,我知道 x1、y1、x2、y2、x3、y3,我想Selected
使用 x1、y1、x2、y2、x3、y3获得直角三角形的值。
重要的是我使用所有 6 个值来找到第 7 个,因为我得到了很多三角形!
有人能帮我吗?
如果你想存储和检索字典的东西,关键是由三角形的三个坐标了-六个值-那么三角形的组合坐标是关键到字典中。
这就是你在这里描述的:
我知道 x1, y1, x2, y2, x3, y3 并且我想使用 x1, y1, x2, y2, x3, y3 获得直角三角形的 Selected 值。
(我回避了 a 是否Dictionary<TriangleRegistryObject, bool>
有意义的问题,而是关注如何将三角形的点用作键。)
假设您实际上创建了一个Dictionary<TriangleRegistryObject, bool>
,其中键是一个三角形,值是一个布尔值,指示它是否被选中。挑战仍然是,为了确定一个键是否重复,字典将使用引用相等。TriangleRegistryObject
具有相同坐标的两个不同实例可能是两个键,这可能不是您想要的。
我们需要的是告诉字典如何比较两个三角形。我们可以通过覆盖Equals
和GetHashCode
on来做到这一点TriangleRegistryObject
。但是,与其更改类以满足这种比较的需要,我们可以只告诉这个特定的字典如何比较三角形(尽管这也可能是一个非常好的解决方案。)
首先,我们将创建一个自定义实现IEqualityComparer<TriangleRegistryObject>
:
public class TriangleComparer : IEqualityComparer<TriangleRegistryObject>
{
public bool Equals(TriangleRegistryObject x, TriangleRegistryObject y)
{
return x.x1.Equals(y.x1)
&& x.y1.Equals(y.y1)
&& x.x2.Equals(y.x2)
&& x.y2.Equals(y.y2)
&& x.x3.Equals(y.x3)
&& x.y3.Equals(y.y3);
}
public int GetHashCode(TriangleRegistryObject obj)
{
unchecked
{
var hashCode = obj.GetHashCode();
hashCode = (hashCode * 397) ^ obj.GetHashCode();
hashCode = (hashCode * 397) ^ obj.GetHashCode();
hashCode = (hashCode * 397) ^ obj.GetHashCode();
hashCode = (hashCode * 397) ^ obj.GetHashCode();
hashCode = (hashCode * 397) ^ obj.GetHashCode();
return hashCode;
}
}
}
(好吧,这看起来并不那么简单。我实际上作弊了,让 Resharper 帮助我生成所有这些。)
现在,如果我们想使用三角形作为字典中的键,我们只需在创建字典时指定该比较器:
var dictionary = new Dictionary<TriangleRegistryObject, bool>(new TriangleComparer());
现在字典将按照我们告诉它的方式比较键,而不是使用引用相等。
或者,如果您只想将相等比较直接添加到三角形本身而不是使用自定义比较器,您可以这样做(忽略Selected
属性):
public class TriangleRegistryObject
{
public double x1 { get; set; }
public double y1 { get; set; }
public double x2 { get; set; }
public double y2 { get; set; }
public double x3 { get; set; }
public double y3 { get; set; }
public override bool Equals(object obj)
{
return base.Equals(obj);
}
protected bool Equals(TriangleRegistryObject other)
{
return x1.Equals(other.x1)
&& y1.Equals(other.y1)
&& x2.Equals(other.x2)
&& y2.Equals(other.y2)
&& x3.Equals(other.x3)
&& y3.Equals(other.y3);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = x1.GetHashCode();
hashCode = (hashCode * 397) ^ y1.GetHashCode();
hashCode = (hashCode * 397) ^ x2.GetHashCode();
hashCode = (hashCode * 397) ^ y2.GetHashCode();
hashCode = (hashCode * 397) ^ x3.GetHashCode();
hashCode = (hashCode * 397) ^ y3.GetHashCode();
return hashCode;
}
}
}
还有一个问题:大概三角形的点不会改变。如果他们可以改变,那么糟糕的事情就会发生。假设您将两个不同的点用作键,然后将其中一个点更改为与另一个点相同。然后你会有重复的键,这会很糟糕。
为了防止这种情况,您可以使三角形类不可变,以便将值传递给构造函数并且永远不能更改。
只是为了涵盖基础,因为我不知道您的应用程序的任何细节:如果您的三角形是结构而不是类,并且其所有成员都是值类型,则将使用值进行比较。如果唯一的值是点(您删除Selected
),那么具有相同点的两个实例将被视为相等,并且您不需要所有额外的比较代码。您仍然希望使结构不可变。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句