C# 中两个对象的相等比较
本文关键字:对象 比较 两个 | 更新日期: 2023-09-27 17:55:48
基本类型的问题,请原谅我如此业余。
案例1:
Employee _emp1 = new Employee();
Employee _emp2 = _emp1;
_emp1.Equals(_emp2) ==> RETURNS a True !!
案例2:
Employee _emp1 = new Employee();
Employee _emp2 = new Employee();
_emp1.Equals(_emp2) ==> RETURNS a False !!
你能解释一下上面的比较方法和内存映射和分配角度的原因吗?
简单地说,默认比较器比较对象实例。
-
在第一个示例中,
_emp1
和_emp2
都指向相同的Employee
实例,因此Equals
返回 true。 -
在第二个示例中,您创建了两个
Employee
对象,_emp1
和_emp2
是两个截然不同的对象。因此,Equals
返回 false。
请注意,不会为引用类型隐式调用复制构造函数。你要做:
Employee _emp1 = new Employee();
Employee _emp2 = new Employee(_emp1); //or _emp1.Clone() if that is implemented
然后Equals
使用默认比较器将返回 false,因为它们是两个唯一的对象。
另请注意,此行为对于值类型并不相同。
此外,如果您(您应该)覆盖Equals
和CompareTo
的默认行为,则上述所有内容都将变得毫无意义。标准技术可能是(假设一点点):
public bool Equals(object rhs)
{
var rhsEmployee = rhs as Employee;
if(rhsEmployee == null) return false;
return this.Equals(rhsEmployee);
}
public bool Equals(Employee rhs)
{
return this.EmployeeId == rhs.EmployeeId;
}
延伸阅读:
-
Object.Equals
-
Object.ReferenceEquals
- 值类型和引用类型
Employee _emp1 = new Employee();
每次您有new Employee()
时,您都会在堆和堆栈中分配新的内存。
表示_emp1是内存中的值,指向堆,例如 1212。
现在你有第二个陈述
Employee _emp2 = new Employee();
所以新值再次_emp2堆中说 1414。
这就是_emp1的原因。等于 (_emp2) 在此处返回 false。
当你说
_emp1 = _emp2
您将在两者中分配相同的值。
"这个苹果属于乔。这个梨属于同一个人。这个苹果的主人和这个梨的主人是同一个人吗?是的。
"这个苹果属于苏珊。这个梨子属于苏珊。这个苹果的主人和这个梨的主人是同一个人吗?不,他们只是碰巧都叫苏珊。
您应该创建自己的Equals
方法。默认情况下,Equals
是从类Object
调用的,这基本上是检查这两个引用是否指向一个对象(即 Object.ReferenceEqual(object, object)
被称为)
当你写Employee _emp1
时,你正在分配内存,该内存是存储指向另一个内存片段的指针所需的内存,该内存将包含 employee 的实例。
new Employee();
分配一个新的内存,用 employee 的实例填充它,并返回此内存的地址(指针)。比如说,1234567。因此,在执行Employee _emp1 = new Employee();
之后,您_emp1
等于1234567,并且1234567指向的内存包含您的员工。
然后你执行Employee _emp2 = _emp1;
,结果是有另一个内存能够包含地址到一个包含雇员(_emp2
)实例的内存,该实例也等于1234567。当你执行_emp1.Equals(_emp2)
结果时,这个me和结果是正确的,因为你的两个变量都指向同一块内存。
在第二种情况下,创建Employee的另一个实例并将其放入不同的内存中(例如7654321之类的内容),并将此地址分配给_emp2
,因此与_emp1
不同。
Employee
,没有实现它自己的.Equals()
方法,那么它使用的是Object.Equals()
,这只是比较引用。在情况 1 中,分配时两个引用相等。
如果要按内部属性比较Employee
对象,则应实现自己的 .Equals()
方法,如果所有这些属性值都匹配,则返回 true,否则返回 false。
没有办法将两个单独的员工实例等同起来,你需要一种方法来等同它们是否相等,因为它们是单独的实例。在第一种情况下,实例相同,_emp2
_emp1
可以通过实现IEquatable<T>
接口来执行此操作。
public class Employee : IEquatable<Employee>
{
public int Id { get; set; }
public bool Equals(Employee other)
{
return other.Id == Id;
}
}
然后,您可以执行此操作
Employee e = new Employee() { Id = 1 };
Employee e2 = new Employee() { Id = 1 };
//Returns true
bool b = e.Equals(e2);