object.Equals()
/// <summary>确定指定的对象是否等于当前对象。</summary> /// <param name="obj">要与当前对象进行比较的对象。</param> /// <returns> /// 如果指定的对象等于当前对象,则为 <see langword="true" />,否则为 <see langword="false" />。 /// </returns> [__DynamicallyInvokable] public virtual bool Equals(object obj) { return RuntimeHelpers.Equals(this, obj); }
namespace ConsoleTest { class Program { static void Main(string[] args) { var a1 = new AA() { Id = 1 }; var a2 = new AA() { Id = 1 }; var a3 = a1; //返回false,引用的不相等 Console.WriteLine($"{a1.Equals(a2)}"); //返回true,引用的不相等 Console.WriteLine($"{a1.Equals(a3)}"); Console.ReadLine(); } } public class AA { public int Id { get; set; } public string Name { get; set; } } }
string.Equals()
/// <summary> /// 确定此实例是否与另一个指定的 <see cref="T:System.String" /> 对象具有相同的值。 /// </summary> /// <param name="value">要与此实例进行比较的字符串。</param> /// <returns> /// 如果 <see langword="true" /> 参数的值与此实例的值相同,则为 <paramref name="value" />;否则为 <see langword="false" />。 /// 如果 <paramref name="value" /> 为 <see langword="null" />,则此方法返回 <see langword="false" />。 /// </returns> [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [__DynamicallyInvokable] public bool Equals(string value) { if (this == null) throw new NullReferenceException(); if (value == null) return false; if ((object) this == (object) value) return true; if (this.Length != value.Length) return false; return string.EqualsHelper(this, value); }
namespace ConsoleTest { class Program { static void Main(string[] args) { var a1 = "123"; var a2 = string.Copy(a1); var a3 = a1; //返回true,引用的不相等,但值相等 Console.WriteLine($"{a1.Equals(a2)}"); //返回true,引用相等 Console.WriteLine($"{a1.Equals(a3)}"); Console.ReadLine(); } } }
值类型.Equals()
/// <summary>指示此实例与指定对象是否相等。</summary> /// <param name="obj">要与当前实例进行比较的对象。</param> /// <returns> /// 如果 <see langword="true" /> 和该实例具有相同的类型并表示相同的值,则为 <paramref name="obj" />;否则为 <see langword="false" />。 /// </returns> [SecuritySafeCritical] [__DynamicallyInvokable] public override bool Equals(object obj) { if (obj == null) return false; RuntimeType type = (RuntimeType) this.GetType(); if ((RuntimeType) obj.GetType() != type) return false; object a = (object) this; if (ValueType.CanCompareBits((object) this)) return ValueType.FastEqualsCheck(a, obj); FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); for (int index = 0; index < fields.Length; ++index) { object obj1 = ((RtFieldInfo) fields[index]).UnsafeGetValue(a); object obj2 = ((RtFieldInfo) fields[index]).UnsafeGetValue(obj); if (obj1 == null) { if (obj2 != null) return false; } else if (!obj1.Equals(obj2)) return false; } return true; }
namespace ConsoleTest { class Program { static void Main(string[] args) { var a1 = new AA() { Name = "1" }; var a2 = new AA() { Name = "1" }; var a3 = a1; //返回true,值相等 Console.WriteLine($"{a1.Equals(a2)}"); //返回true,值相等,引用相等 Console.WriteLine($"{a1.Equals(a3)}"); Console.ReadLine(); } } public struct AA { public string Name { get; set; } } }
静态Equals(),最后还是调用object.Equals()
/// <summary>确定指定的对象实例是否被视为相等。</summary> /// <param name="objA">要比较的第一个对象。</param> /// <param name="objB">要比较的第二个对象。</param> /// <returns> /// 如果对象被视为相等,则为 <see langword="true" />,否则为 <see langword="false" />。 /// 如果 <paramref name="objA" /> 和 <paramref name="objB" /> 均为 null,此方法将返回 <see langword="true" />。 /// </returns> [__DynamicallyInvokable] public static bool Equals(object objA, object objB) { if (objA == objB) return true; if (objA == null || objB == null) return false; return objA.Equals(objB); }
namespace ConsoleTest { class Program { static void Main(string[] args) { AA a1 = new AA() { Name = "1" }; AA a2 = new AA() { Name = "1" }; BB b1 = new BB() { Name = "1" }; BB b2 = new BB() { Name = "1" }; //返回true,引用相等 Console.WriteLine($"{Equals(a1, a2)}"); //返回true,值相等 Console.WriteLine($"{Equals(b1, b2)}"); //null和null是相等的,返回true Console.WriteLine($"{Equals(null, null)}"); Console.ReadLine(); } } public class AA { public string Name { get; set; } } public struct BB { public string Name { get; set; } } }
实现IEquatable<T>接口
namespace ConsoleTest { class Program { static void Main(string[] args) { var a1 = new AA() { Name = "1" }; var a2 = new AA() { Name = "1" }; // true Console.WriteLine($"{a1.Equals(a2)}"); // true Console.WriteLine($"{Equals(a1, a2)}"); Console.ReadLine(); } } public class AA : IEquatable<AA> { public string Name { get; set; } //a1.Equals(a2)调用 public bool Equals(AA other) { return this.Name.Equals(other.Name); } //Equals(a1, a2)调用 public override bool Equals(Object obj) { return this.Name.Equals((obj as AA)?.Name); } } }
==操作符
==默认并没有使用Equals方法,而是比较的是栈内的内容,对于值类型而言,”==“比较的就是两个对象的值,引用类型比较的就是两个引用类型在栈内的地址
string类型是特殊的重载了==方法,没调用默认==方法
class Program { static void Main(string[] args) { var a1 = new AA() { Name = "1" }; var a2 = new AA() { Name = "1" }; var a3 = new AA() { Name = "2" }; // true Console.WriteLine($"{a1.Equals(a2)}"); // true Console.WriteLine($"{Equals(a1, a2)}"); // true Console.WriteLine($"{a1 == a2}"); // true Console.WriteLine($"{a1 != a3}"); Console.ReadLine(); } } public class AA : IEquatable<AA> { public string Name { get; set; } /// <summary> /// IEquatable 实现IEquatable接口 a1.Equals(a2) /// </summary> /// <param name="other"></param> /// <returns></returns> public bool Equals(AA other) { return this.Name.Equals(other.Name); } /// <summary> /// 重载基类Equals方法 Equals(a1, a2) /// </summary> /// <param name="obj"></param> /// <returns></returns> public override bool Equals(Object obj) { return this.Name.Equals((obj as AA)?.Name); } /// <summary> /// 运算符重载 相等 /// </summary> /// <param name="a1"></param> /// <param name="a2"></param> /// <returns></returns> public static bool operator ==(AA a1, AA a2) { return a1.Name.Equals(a2.Name); } /// <summary> /// 运算符重载 不等 /// </summary> /// <param name="a1"></param> /// <param name="a2"></param> /// <returns></returns> public static bool operator !=(AA a1, AA a2) { return !(a1 == a2); } }