我有一个名为Point的类,它正在重载" =="和"!="运算符比较两个Point对象。如何将我的Point对象与" null"进行比较,这是一个问题,因为当我调用==或!=运算符时,null为Equals方法中的问题。请打开一个控制台应用程序,看看我想说什么。如何解决它。
public class Point
{
public int X { get; set; }
public int Y { get; set; }
public static bool operator == (Point p1,Point p2)
{
return p1.Equals(p2);
}
public static bool operator != (Point p1, Point p2)
{
return !p1.Equals(p2);
}
public override bool Equals(object obj)
{
Point other = obj as Point;
//problem is here calling != operator and this operator calling this method again
if (other != null)
{
if (this.X == other.X && this.Y == other.Y)
{
return true;
}
return false;
}
else
{
throw new Exception("Parameter is not a point");
}
}
}
class Program
{
static void Main(string[] args)
{
Point p1 = new Point { X = 9, Y = 7 };
Point p2 = new Point { X = 5, Y = 1 };
p1.X = p2.X;
p1.Y = p2.Y;
bool b1=p1==p2;
Console.ReadKey();
}
}
答案 0 :(得分:4)
使用ReferenceEquals
检查null
:
if (ReferenceEquals(other, null))
话虽如此,Equals
如果遇到未知对象类型通常不会抛出异常,它应该只返回false
,因此这是我要编写的方法:
public override bool Equals(object obj)
{
Point other = obj as Point;
if (ReferenceEquals(other, null))
return false;
return (this.X == other.X && this.Y == other.Y);
}
另一个问题是,如果您将null
与某些内容进行比较,您的运算符将抛出异常,因为您无法在null
引用上调用实例方法。
因此,这是我写的完整课程:
public class Point
{
public int X { get; set; }
public int Y { get; set; }
public static bool operator == (Point p1,Point p2)
{
if (ReferenceEquals(p1, p2)) return true;
if (ReferenceEquals(p1, null)) return false;
return p1.Equals(p2);
}
public static bool operator != (Point p1, Point p2)
{
return !(p1 == p2);
}
public bool Equals(Point other)
{
if (ReferenceEquals(other, null))
return false;
return (this.X == other.X && this.Y == other.Y);
}
public override bool Equals(object obj)
{
Point other = obj as Point;
if (ReferenceEquals(other, null))
return false;
return Equals(other);
}
}
答案 1 :(得分:1)
您不应该在以下位置抛出异常:
if (other != null)
{
...
}
else
{
throw new Exception("Parameter is not a point");
}
您可以阅读http://msdn.microsoft.com/en-US/library/336aedhh%28v=vs.85%29.aspx,了解Equals()
如何正确实施。
答案 2 :(得分:1)
在C#中处理相等性可能很棘手,并且很容易陷入像你在这里遇到过的陷阱。
在处理相等时,我总是遵循相同的模式,无论是在值类型中还是在引用类型中(显然除了null
检查):实现一个静态的私有帮助器方法来处理所有可能性,并让所有等式检查都会调用此方法。
因此,在您的情况下,我会执行以下操作:
更新 :修正了一个拼写错误,equals
应该是private
,而不是public
。
private static bool equals(Point p1, Point p2)
{
if (object.ReferenceEquals(p1, p2))
return true;
if (object.ReferenceEquals(p1, null) || object.ReferenceEquals(p2, null))
return false;
return p1.X == p2.X && p1.Y == p2.Y;
}
好的,那我们在这做什么呢?
我们首先检查两个对象是否具有相同的引用。如果
就是这样,那么它们必须是平等的,因为它们是相同的
宾语。请注意,这会处理null == null
案例。
然后我们检查两个参数中的任何一个是否等于null
。
如果是,那么我们就知道p1
和p2
不相等。
要查看参数是否等于null
,我们使用satic方法
bool object.ReferenceEquals(,)
以避免您遇到的问题
这又是你的平等实施。
最后,我们现在知道我们有两个非空Point
参数,所以我们去了
提前并实现两个Point
对象的特定相等逻辑。
通过这种简单的方法,我们在课堂上处理了所有可能的等式检查。现在我们只需要从所有可能的相等方法和运算符中调用此方法:
public static bool operator ==(Point p1, Point p2)
{
return Point.equals(p1, p2);
}
public static bool operator !=(Point p1, Point p2)
{
return !Point.equals(p1, p2);
}
public override bool Equals(object obj)
{
return Point.equals(this, obj as Point);
}
另外,您应该实现非常简单的IEquatable<Point>
接口。这在处理值类型时特别相关,因为在执行相等性检查时避免装箱转换:
public bool Equals(Point p)
{
return Point.equals(this, p);
}
最后但并非最不重要的是,您要覆盖Equals
方法以及==
和!=
运算符,因此您还应该以与您的平等一致的方式覆盖int GetHashCode()
实施:如果p1 == p2
,那么p1.GetHashCode()
必须等于p1.GetHashCode()
(注意,这并不意味着如果p1 != p2
,p1.GetHashCode()
必须不等于p2.GetHashCode()
):
public override int GetHashCode()
{
return this.X ^ this.Y;
}
希望这个小指南有所帮助。
答案 3 :(得分:0)
也许是这样的:
public override bool Equals(object obj)
{
if (obj != null && obj is Point)
{
Point other = (Point)obj;
if (this.X == other.X && this.Y == other.Y)
{
return true;
}
return false;
}
return false;
}