本文介绍了在结构上实现==的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定任何结构,使其成员都是值类型,

Given any struct, such that its members are all value types,

struct happy
{
    int foo;
    char bar;
}



ValueType.Equals(对象其他)自动正常工作。



那么为什么,如果我实现 == 运算符,我警告覆盖 ValueType.Equals ? (更正:我总是打开警告错误



如果结构包含引用类型,这是一个安全措施吗?



覆盖ValueType.Equals 只是为了调用 base.Equals



什么是最佳做法?

  • 覆盖等于和GetHashCode,只需调用base
  • 禁用警告 #pragma
  • 实际对所有成员实施相等检查或使用哈希码生成

  • ValueType.Equals(object other) works correctly automatically.

    So why, if I implement the == operator, am I warned to override ValueType.Equals? (Correction: I always have Warnings as Errors turned on)

    Is this a safeguard in case the struct contains reference types?

    Is it bad form to override ValueType.Equals just to call base.Equals?

    What is considered best practice?

    • override Equals and GetHashCode and just call base
    • disable warning with #pragma
    • actually implement equality checks on all members or using hashcode generation
    • ?
    • 推荐答案


          /// <include file='doc\Color.uex' path='docs/doc[@for="Color.operator=="]/*' />
          /// <devdoc>
          ///    <para>
          ///       Tests whether two specified <see cref='System.Drawing.Color'/> objects
          ///       are equivalent.
          ///    </para>
          /// </devdoc>
          public static bool operator ==(Color left, Color right) {
              if (left.value == right.value
                  && left.state == right.state
                  && left.knownColor == right.knownColor) {
      
                  if (left.name == right.name) {
                      return true;
                  }
      
                  if (left.name == (object) null || right.name == (object) null) {
                      return false;
                  }
      
                  return left.name.Equals(right.name);
              }
      
              return false;
          }
      
          /// <include file='doc\Color.uex' path='docs/doc[@for="Color.operator!="]/*' />
          /// <devdoc>
          ///    <para>
          ///       Tests whether two specified <see cref='System.Drawing.Color'/> objects
          ///       are equivalent.
          ///    </para>
          /// </devdoc>
          public static bool operator !=(Color left, Color right) {
              return !(left == right);
          }
      
          /// <include file='doc\Color.uex' path='docs/doc[@for="Color.Equals"]/*' />
          /// <devdoc>
          ///    Tests whether the specified object is a
          /// <see cref='System.Drawing.Color'/>
          /// and is equivalent to this <see cref='System.Drawing.Color'/>.
          /// </devdoc>
          public override bool Equals(object obj) {
              if (obj is Color) {
                  Color right = (Color)obj;
                  if (value == right.value
                      && state == right.state
                      && knownColor == right.knownColor) {
      
                      if (name == right.name) {
                          return true;
                      }
      
                      if (name == (object) null || right.name == (object) null) {
                          return false;
                      }
      
                      return name.Equals(name);
                  }
              }
              return false;
          }
      
          /// <include file='doc\Color.uex' path='docs/doc[@for="Color.GetHashCode"]/*' />
          /// <devdoc>
          ///    <para>[To be supplied.]</para>
          /// </devdoc>
          public override int GetHashCode() {
              return  value.GetHashCode() ^
                      state.GetHashCode() ^
                      knownColor.GetHashCode();
          }
      }





      Mono的平等实施:



      Mono's equality implementation:

      /// <summary>
      /// Equality Operator
      /// </summary>
      ///
      /// <remarks>
      /// Compares two Color objects. The return value is
      /// based on the equivalence of the A,R,G,B properties
      /// of the two Colors.
      /// </remarks>
      
      public static bool operator == (Color left, Color right)
      {
          if (left.Value != right.Value)
              return false;
          if (left.IsNamedColor != right.IsNamedColor)
              return false;
          if (left.IsSystemColor != right.IsSystemColor)
              return false;
          if (left.IsEmpty != right.IsEmpty)
              return false;
          if (left.IsNamedColor) {
              // then both are named (see previous check) and so we need to compare them
              // but otherwise we don't as it kills performance (Name calls String.Format)
              if (left.Name != right.Name)
                  return false;
          }
          return true;
      }
      
      /// <summary>
      /// Inequality Operator
      /// </summary>
      ///
      /// <remarks>
      /// Compares two Color objects. The return value is
      /// based on the equivalence of the A,R,G,B properties
      /// of the two colors.
      /// </remarks>
      
      public static bool operator != (Color left, Color right)
      {
          return ! (left == right);
      }
      
      		/// <summary>
      		///	Equals Method
      		/// </summary>
      		///
      		/// <remarks>
      		///	Checks equivalence of this Color and another object.
      		/// </remarks>
      
      		public override bool Equals (object obj)
      		{
      			if (!(obj is Color))
      				return false;
      			Color c = (Color) obj;
      			return this == c;
      		}
      
      		/// <summary>
      		///	Reference Equals Method
      		///	Is commented out because this is handled by the base class.
      		///	TODO: Is it correct to let the base class handel reference equals
      		/// </summary>
      		///
      		/// <remarks>
      		///	Checks equivalence of this Color and another object.
      		/// </remarks>
      		//public bool ReferenceEquals (object o)
      		//{
      		//	if (!(o is Color))return false;
      		//	return (this == (Color) o);
      		//}
      
      
      
      		/// <summary>
      		///	GetHashCode Method
      		/// </summary>
      		///
      		/// <remarks>
      		///	Calculates a hashing value.
      		/// </remarks>
      
      		public override int GetHashCode ()
      		{
      			int hc = (int)(Value ^ (Value >> 32) ^ state ^ (knownColor >> 16));
      			if (IsNamedColor)
      				hc ^= Name.GetHashCode ();
      			return hc;
      		}


      struct happy : IEquatable<happy>
      {
         int foo;
         char bar;
      
         public bool Equals(happy value)
         {
            return ((this.foo == value.foo) && (this.bar == value.bar));
         }
      
         override bool Equals(object obj)
         {
            return ((obj is happy) && obj.Equals(this));
         }
      
         public static bool operator ==(happy left, happy right)
         {
            return left.Equals(right);
         }
      
         public static bool operator !=(happy left, happy right)
         {
            return !left.Equals(right);
         }
      
         public override int GetHashCode()
         {
            return foo.GetHashCode() ^ (bar.GetHashCode() << 5);
         }
      }





      (GetHashCode实现只是一个简单的例子,你必须要注意有你选择的算法没有碰撞)



      希望这会有所帮助。



      (GetHashCode implementation is just a quick example, you have to take care that there are no collisions in the algorithm you choose)

      Hope this helps.


      这篇关于在结构上实现==的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 23:01