2013-01-25 55 views
4

这是一个基本类型的问题,原谅我是如此的业余。在C中的两个对象的平等比较#

案例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 !! 

你能解释我interms内存映射和分配的角度看上面的对比方法和原因是什么?

+3

案例1令您惊讶吗? C++背景? –

+0

@Damien_The_Unbeliever我想是的,宾果! – Cris

+1

-1抱歉,但我不认为SO是这个级别问题的地方。这种事情已经在MSDN和博客中引起了麻烦。 – DeanOC

回答

3
Employee _emp1 = new Employee(); 

每次你在堆和栈分配新的内存。

意味着_emp1在内存指着堆说,1212

现在你有第二次发言

Employee _emp2 = new Employee(); 

所以,再一次新的价值_emp2说1414堆中的​​价值。

这就是为什么_emp1.Equals(_emp2)在这里返回false。

当你说

_emp1 = _emp2 

你分配在两个相同的值。

3

“这个苹果属于乔,这个梨属于同一个人,这个苹果的主人是这个梨主人的同一个人吗?是的。”

“这个苹果属于苏珊,这个梨属于苏珊,这个苹果的主人是这个梨主人的同一个人吗?不,他们恰好都被称为苏珊。

2

您应该创建自己的Equals方法。默认EqualsObject类被调用,基本上检查这两个引用是否指向一个对象(即调用Object.ReferenceEqual(object, object)

9

简而言之,默认比较器比较对象实例。

  • 在你的第一个例子中,无论是_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,因为它们是两个唯一对象。

另请注意,对于值类型,此行为是不一样


而且,如果你(你应该)覆盖的EqualsCompareTo默认行为,所有上述变得毫无意义。一个标准的技术可能是(假设一点点):

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; 
} 

进一步阅读:

+0

在您的第一个项目符号中,您的意思是说_emp1和_emp2都指向相同的内存位置。并在第二个_emp1和_emp2指向两个不同的内存位置。那么这和Stacks,堆有什么关系? –

+1

@ LetsKickSomeAssin.net在语义上它是一回事,是的。但是,在托管世界中,我们倾向于避免直接谈论关于记忆的事情,因为我们通常没有直接控制记忆。但是,是的,它正在检查比较两个指针值的[Object.ReferenceEquals](http://msdn.microsoft.com/en-us/library/system.object.referenceequals.aspx)。 –

+0

这将不会编译,因为编译器拒绝将'null'转换为'bool'。如果另一个实例不是'Employee','Equals'应该返回'false'。 – Nuffin

1

Employee,没有实现它自己的.Equals()方法,那么它使用的是Object.Equals(),它只是比较引用。在情况1中,分配时两个参考值相等。

如果要将Employee对象与其内部属性进行比较,则应该实现自己的.Equals()方法,如果所有这些属性值都匹配,则返回true;否则返回false。

1

没有办法将雇员的两个单独实例等同起来,您需要一种方法来将他们是否相等,因为他们是单独的实例。在情况一中,实例是相同的,并且_emp2_emp1您可以通过执行IEquatable<T>接口来完成此操作。

public class Employee : IEquatable<Employee> 
{ 
    public int Id { get; set; } 

    public bool Equals(Employee other) 
    { 
    return other.Id == Id; 
    } 
} 

然后就可以做到这一点,你有new Employee()

Employee e = new Employee() { Id = 1 }; 
Employee e2 = new Employee() { Id = 1 }; 
//Returns true 
bool b = e.Equals(e2); 
1

当您编写Employee _emp1时,您正在分配内存,该内存用于存储指向另一个包含Employee实例的内存的指针。

new Employee();分配一个新的内存填充它与一个员工的实例,并返回你这个内存(指针)的地址。比如说,1234567.因此,在执行Employee _emp1 = new Employee();之后,您的_emp1等于1234567,而1234567指向的内存包含您的员工。

然后你执行Employee _emp2 = _emp1;,结果是有另一块内存能够包含一个地址到一个包含Employee实例(_emp2)的内存,它也等于1234567。这一点,当你执行_emp1.Equals(_emp2)时,结果是真实的,因为你的两个变量都指向同一块内存。

在第二种情况下,Employee的另一个实例被创建并放入不同的内存中(例如类似于7654321),并且该地址被指定为_emp2,因此与_emp1不同。