关于 warning CS0659:“***”重写Object.Equals(object o)但不重写Object.GetHashCode()

时间:2022-03-27 16:17:26

对象相等性和同一性

  • System.Object 类型提供了以下方法,
  • 关于 warning CS0659:“***”重写Object.Equals(object o)但不重写Object.GetHashCode()关于 warning CS0659:“***”重写Object.Equals(object o)但不重写Object.GetHashCode()
     1 namespace System
    2 {
    3 //
    4 // 摘要:
    5 // 支持 .NET Framework 类层次结构中的所有类,并为派生类提供低级别服务。这是 .NET Framework 中所有类的最终基类;它是类型层次结构的根。
    6 [ClassInterface(ClassInterfaceType.AutoDual)]
    7 [ComVisible(true)]
    8 public class Object
    9 {
    10 //
    11 // 摘要:
    12 // 初始化 System.Object 类的新实例。
    13 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
    14 public Object();
    15
    16 //
    17 // 摘要:
    18 // 允许对象在“垃圾回收”回收之前尝试释放资源并执行其他清理操作。
    19 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    20 ~Object();
    21
    22 //
    23 // 摘要:
    24 // 确定指定的对象实例是否被视为相等。
    25 //
    26 // 参数:
    27 // objA:
    28 // 要比较的第一个对象。
    29 //
    30 // objB:
    31 // 要比较的第二个对象。
    32 //
    33 // 返回结果:
    34 // 如果认为对象相等,则为 true;否则为 false。如果 objA 和 objB 都为 null,则方法返回 true。
    35 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
    36 public static bool Equals(Object objA, Object objB);
    37 //
    38 // 摘要:
    39 // 确定指定的 System.Object 实例是否是相同的实例。
    40 //
    41 // 参数:
    42 // objA:
    43 // 要比较的第一个对象。
    44 //
    45 // objB:
    46 // 要比较的第二个对象。
    47 //
    48 // 返回结果:
    49 // 如果 objA 是与 objB 相同的实例,或如果两者均为 null,则为 true;否则,为 false。
    50 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    51 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
    52 public static bool ReferenceEquals(Object objA, Object objB);
    53 //
    54 // 摘要:
    55 // 确定指定的对象是否等于当前对象。
    56 //
    57 // 参数:
    58 // obj:
    59 // 要与当前对象进行比较的对象。
    60 //
    61 // 返回结果:
    62 // 如果指定的对象等于当前对象,则为 true;否则为 false。
    63 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
    64 public virtual bool Equals(Object obj);
    65 //
    66 // 摘要:
    67 // 作为默认哈希函数。
    68 //
    69 // 返回结果:
    70 // 当前对象的哈希代码。
    71 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
    72 public virtual int GetHashCode();
    73 //
    74 // 摘要:
    75 // 获取当前实例的 System.Type。
    76 //
    77 // 返回结果:
    78 // 当前实例的准确运行时类型。
    79 [SecuritySafeCritical]
    80 public Type GetType();
    81 //
    82 // 摘要:
    83 // 返回表示当前对象的字符串。
    84 //
    85 // 返回结果:
    86 // 表示当前对象的字符串。
    87 public virtual string ToString();
    88 //
    89 // 摘要:
    90 // 创建当前 System.Object 的浅表副本。
    91 //
    92 // 返回结果:
    93 // 当前 System.Object 的浅表副本。
    94 [SecuritySafeCritical]
    95 protected Object MemberwiseClone();
    96 }
    97 }
    Syste.Object
  • 其中提供了名为Equals的虚方法,它的作用是在两个对象相等的前提下返回true.
  • 关于 warning CS0659:“***”重写Object.Equals(object o)但不重写Object.GetHashCode()Equals方法初实现

    看起来似乎是合理的实现,但问题是如果实参引用不同的对象,Equals就不能判断对象是否包含相同的值,就会判定为False.对于Object的Equals的默认实现,它实现的是同一性,而非相等性。

  • 针对以下问题,1)obj实参是否为null,2)this和obj实参是否是引用同一个对象,3)this和obj实参是否引用不同类型的对象,实现Object的Equals方法。
  • 关于 warning CS0659:“***”重写Object.Equals(object o)但不重写Object.GetHashCode()关于 warning CS0659:“***”重写Object.Equals(object o)但不重写Object.GetHashCode()
     1  public class Object
    2 {
    3 public virtual Boolean Equals(Object obj)
    4 {
    5 if (obj == null)
    6 return false;
    7 if (this.GetType() != obj.GetType())
    8 return false;
    9
    10 return true; ;
    11 }
    12 }
    Equals方法
  • 一个类型重写Equals方法时,重写的方法应调用基类的Equals实现(除非这个基类就是Object).另外一个类型能重写Object的Equals方法,所以不能在调用这个Equals方法来测试同一性。Object提供了一个静态方法ReferenceEquals,其原型如下:
  • 关于 warning CS0659:“***”重写Object.Equals(object o)但不重写Object.GetHashCode()关于 warning CS0659:“***”重写Object.Equals(object o)但不重写Object.GetHashCode()
    1  public Boolean ReferenceEquals(Object objA, Object objB)
    2 {
    3 return (objA == objB);
    4 }
    ReferenceEquals

    如果想检查同一性(看两个引用是否指向同一个对象),那么务必调用ReferenceEquals,而不应使用C#的==操作符(除非先把两个操作数都转型为Object)

  • ValueType的Equals方法使用反射技术,由于CLR的反射机制较慢,所以在定义自己的值类型时,应该重写Equals方法,提供自己的实现,以便在用类型的实例进行值的相等性比较时提高性能。当然,在自己的视线中,不要调用base.Equals。
  • 定义自己的类型时,如果决定重写Equals,必须确定它符合相等性的4个特征。
  • 1)Equals必须是自反的。
  • 2)Equals必须是对称的。
  • 3)Equals必须是可传递的。
  • 4)Equals必须是一致的。
  • 重写Equals方法,还要:
  • 让类型实现System.IEquatable<T>接口的Equals方法。这个泛型接口允许你定义一个类型安全的Equals方法。
  • 重载==和!=操作符方法 通常应事先这些操作符方法,在内部调用类型安全的Equals方法.

除此之外,假如以后出于排序的目的而比较类型的实例,那么类型华英实现System.IComparable的CompareTo方法和System.IComparable<T>的CompareTo方法。

对象哈希吗

System.Object提供了虚方法GetHashCode,它能获取任意对象的Int32哈希吗。

  • 如果定义的一个类型重写了Equals方法,那么还应重写GetHashCode()方法。如果定义的类型在重写Equals的同时没有重写GetHashCode(),Microsoft的C#编译器会报告一条警告消息,例如以下类型,会显示警告消息:warning CS0659:“Program”重写Object.Equals(object o)但不重写Object.HetHashCode().
  • 关于 warning CS0659:“***”重写Object.Equals(object o)但不重写Object.GetHashCode()重写Equals

    之所以要同时定义GetHashCode,是因为在System.Collections.Hashtable类型、System.Collections.Generic.Dictionary类型以及其他一些集合的实现中,要求两个对象为了相等,必须具有相同的哈希吗,所以,如果重写了Equals,那么还应重写GetHashCode,确保相等性算法和对象哈希吗算法是一致的。

  • 关于 warning CS0659:“***”重写Object.Equals(object o)但不重写Object.GetHashCode()关于 warning CS0659:“***”重写Object.Equals(object o)但不重写Object.GetHashCode()
    1 internal sealed class Point
    2 {
    3 private Int32 m_x, m_y;
    4 public override int GetHashCode()
    5 {
    6 return m_x ^ m_y;
    7 }
    8 }
    GetHashCode