C# &引用;等于;无法在重载运算符函数中调用?
我发现了一件有趣的事情,把它当作一个C#程序:C# &引用;等于;无法在重载运算符函数中调用?,c#,.net,C#,.net,我发现了一件有趣的事情,把它当作一个C#程序: 命名空间控制台应用程序1 { 使用制度; 公立班学生 { 公共int ID{get;set;} 公共字符串名称{get;set;} 公共覆盖布尔等于(对象比较学生) { 学生stu=比较学生作为学生; if(stu==null) { 返回false; } 返回ID.Equals(stu.ID)和&Name.Equals(stu.Name); } 公共覆盖int GetHashCode() { 返回ID.GetHashCode()^Name.GetH
命名空间控制台应用程序1
{
使用制度;
公立班学生
{
公共int ID{get;set;}
公共字符串名称{get;set;}
公共覆盖布尔等于(对象比较学生)
{
学生stu=比较学生作为学生;
if(stu==null)
{
返回false;
}
返回ID.Equals(stu.ID)和&Name.Equals(stu.Name);
}
公共覆盖int GetHashCode()
{
返回ID.GetHashCode()^Name.GetHashCode();
}
///
///请注意,这将导致NullPointException……为什么?
///如果我使用“returns1.ID==s2.ID&&s1.Name==s2.Name”,就可以了。
///
公共静态布尔运算符==(学生s1、学生s2)
{
返回s1。等于(s2);
}
公共静态布尔运算符!=(学生s1、学生s2)
{
返回!s1.等于(s2);
}
}
公共课程
{
静态void Main(字符串[]参数)
{
学生s1=新学生();
s1.ID=1;
s1.Name=“YourName”;
学生s2=新学生();
s2.ID=1;
s2.Name=“YourName”;
//为什么这里有异常(NullPoint异常)
bool-isname=(s1==s2);
Console.WriteLine(ISName);
}
}
}
如果复制我的代码并运行,将抛出NullPointer异常。为什么?
PS:如果我在重载操作符+中使用“returns1.ID==s2.ID&&s1.Name==s2.Name”,那就可以了
为什么??我正在使用net4.0 VS2015
如果您通过将调试点放在“bool isSame=(s1==s2);”处进行调试,您很快就会发现它进入了“==”重载函数3次,最后,s1和s2为null 虽然Ians评论将解决上述问题,但它不会最终解决一般问题。 问题的根源在于比较运算符的重载 程序员希望
null==myobject
以及myobject==null
都是有效的表达式(在.Equals
的实现中也是如此)。这不适用于上述类,因为调用了operator==
中的成员函数s1.Equals
因此,任何合理的比较运算符重载都应该能够处理真正的任何输入,而不会引发异常。如果有疑问,只需返回false即可。
这包括空值以及尚未分配所有属性的类实例
public static bool operator ==(Student s1, Student s2) =>
ReferenceEquals(s1, s2) || (!ReferenceEquals(s1, null) && s1.Equals(s2));
理由:
处理ReferenceEquals(s1,s2)
以及null==null
。后者不需要比较内容x==x
句柄s1!=null
null==x
已由x==null
实现处理.Equals
IEquatable
重载相等运算符时,建议提供强类型.Equals
实现
此外,您不应该使用.Equals
来比较组件,因为如果到目前为止还没有分配名称
,这将由于类似的原因而失败
public override bool Equals(object obj) =>
Equals(obj as Student);
public bool Equals(Student stu) =>
!ReferenceEquals(stu, null) && ID == stu.ID && Name == stu.Name;
另请参见Yuval Itzhakov对问题的答复尽管Ians的评论将解决上述问题,但它不会最终解决一般问题。 问题的根源在于比较运算符的重载 程序员希望
null==myobject
以及myobject==null
都是有效的表达式(在.Equals
的实现中也是如此)。这不适用于上述类,因为调用了operator==
中的成员函数s1.Equals
因此,任何合理的比较运算符重载都应该能够处理真正的任何输入,而不会引发异常。如果有疑问,只需返回false即可。
这包括空值以及尚未分配所有属性的类实例
public static bool operator ==(Student s1, Student s2) =>
ReferenceEquals(s1, s2) || (!ReferenceEquals(s1, null) && s1.Equals(s2));
理由:
处理ReferenceEquals(s1,s2)
以及null==null
。后者不需要比较内容x==x
句柄s1!=null
null==x
已由x==null
实现处理.Equals
IEquatable
重载相等运算符时,建议提供强类型.Equals
实现
此外,您不应该使用.Equals
来比较组件,因为如果到目前为止还没有分配名称
,这将由于类似的原因而失败
public override bool Equals(object obj) =>
Equals(obj as Student);
public bool Equals(Student stu) =>
!ReferenceEquals(stu, null) && ID == stu.ID && Name == stu.Name;
另请参见Yuval Itzhakov对问题的回答,而不是
stu==null
useobject.ReferenceEquals(stu,null)
@IanMercer:但为什么在调试中调用了3次运算符函数?最后,s1=s2=null?而不是stu==null
使用object.ReferenceEquals(stu,null)
@IanMercer:但是为什么在调试中调用了3次操作符函数呢?最后,s1=s2=null?这是IEquatable
。没有这样的接口IEqualityComparable
(虽然有一个IEqualityComparer
,但它的用途有些不同)它是IEquatable
。没有这样的接口IEqualityComparable
(虽然有一个IEqualityComparer
,但它的用途有些不同)