Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# &引用;等于;无法在重载运算符函数中调用?_C#_.net - Fatal编程技术网

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

我发现了一件有趣的事情,把它当作一个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.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
use
object.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
,但它的用途有些不同)