다음을 통해 공유


.NET: Equality Features

**Introduction **

The .NET equality features are:

The first 3 features are part of the System.Object class as in the following:

http://www.c-sharpcorner.com/UploadFile/91c28d/working-with-net-equality-features469/Images/codeobject.png

Virtual Object.Equals() method for reference types

This method gives us reference equality for most reference types, but the value equality for all value types.

class Person  
{  
    public int  Id { get; set; }  
    public string  Name { get; set; }  
    public Person(int id ,string name)  
    {  
       this.Id = id;  
       this.Name = name;  
    }  
}

The Person class has two the properties Id and Name and a constructor that forces to set the Id and Name.

class Program  
{
    static void  Main(string[] args)  
    {  
       Person Person1 = new  Person(1,"Anil");  
       Person Person2 = new  Person(1, "Anil");  
       Console.WriteLine(Person1.Equals(Person2));  
       Console.ReadLine();  
    }  
}

There are two instances, Person1 and Person2. Both are different instances but the values are the same (ID = 1 and Name = “Anil”).

http://www.c-sharpcorner.com/UploadFile/91c28d/working-with-net-equality-features469/Images/false.jpg

Person1 and Person2 are different instances so the reference equality evaluates to false.

Virtual Object.Equals() method for value types

To demonstrate Virtual Object.Equals(), change the person class to a struct. We all know that class is a reference type and struct is a value type.

public struct  Person  
   {  
       private int  id;  
   
       public int  Id  
       {  
           get { return id; }  
             
       }  
       private string  name ;  
   
       public string  Name  
       {  
           get { return name; }  
           
       }  
          
          
       public Person(int id ,string name)  
       {  
           this.id = id;  
           this.name = name;  
       }  
   }

There is no change in the Main Method, but different output, because Object.Equals() compares values for struct by default.

class Program  
    {  
        static void  Main(string[] args)  
        {  
            Person Person1 = new  Person(1,"Anil");  
            Person Person2 = new  Person(1, "Anil");  
            Console.WriteLine(Person1.Equals(Person2));  
            Console.ReadLine();  
        }  
    }

http://www.c-sharpcorner.com/UploadFile/91c28d/working-with-net-equality-features469/Images/true.jpg

Equals() is a virtual method of System. Object but inside the Value type class there is an override for Equals(). It checks all the fields and return true only if all fields are equal.

http://www.c-sharpcorner.com/UploadFile/91c28d/working-with-net-equality-features469/Images/classprogram.png
Virtual equality method has one problem. It will throw an error for null reference

http://www.c-sharpcorner.com/UploadFile/91c28d/working-with-net-equality-features469/Images/Picture1.png
If person1 is null then it will throw an error. We can overcome this issue using the Static Equals() method.

Static Equals() Method

Change the preceding program with static Equals().

class Program  
{  
   static void  Main(string[] args)  
   {  
      Person Person1 = null;// new Person(1, "Anil");  
      Person Person2 = new  Person(1, "Anil");  
      Console.WriteLine(object.Equals(Person1, Person2));  
      Console.ReadLine();  
              
   }  
}

  Output:

http://www.c-sharpcorner.com/UploadFile/91c28d/working-with-net-equality-features469/Images/output%20false.jpg

The following are the problems of the Equals() method:

  • Lack of strong typing 
  • Need to box value types.

Static Object.ReferenceEquals method

 

The ReferenceEquals method checks whether two variables refer to the same instance. Both the virtual Equals() and the static Equals() usually compare references but not if overridden. As we all know static methods are never overridable. So the static ReferenceEquals() behaviour cannot be changed.

Consider the following example. 

class Program 
    { 
        static void Main(string[] args) 
        { 
            //Person Person1 = null;// new Person(1, "Anil"); 
            //Person Person2 = new Person(1, "Anil"); 
            string person1 = "anil"; 
            string person2 = string.Copy(person1); 
            Console.WriteLine(person1.Equals(person2)); 
            Console.WriteLine(Object.ReferenceEquals(person1,person2)); 
            Console.ReadLine(); 
               
        } 
    }

Equals() and ReferenceEquals() will return different output.

http://www.c-sharpcorner.com/UploadFile/91c28d/working-with-net-equality-features469/Images/truefalse.jpg

Equals() checks the value and ReferenceEquals() check the references.

IEquatable<T> Interface

  Equals() has some problems. In Figure 1 we can see Equals() has a parameter type object. It's a reference type, the value type will be boxed and that will give a performance hit. Equals() is not type-safe.

class Program  
    {  
        static void  Main(string[] args)  
        {  
            Person Person1 = new  Person(1, "Anil");  
            List<int> list = new  List<int>();  
            Console.WriteLine(Person1.Equals(list));  
            Console.ReadLine();  
              
        }  
    }

In the preceding example “Person1” is a type of Person class and “list” is a list of integers. Both are totally different. But the compiler allows us to compare these two. To solve this problems Microsoft introduced the IEquatable<T> interface. Here the Equals() method has a parameter with type T.

http://www.c-sharpcorner.com/UploadFile/91c28d/working-with-net-equality-features469/Images/green%20code.jpg

This would solve boxing and type safety. See the following picture:

http://www.c-sharpcorner.com/UploadFile/91c28d/working-with-net-equality-features469/Images/void%20main%20bollean.jpg

http://www.c-sharpcorner.com/UploadFile/91c28d/working-with-net-equality-features469/Images/void%20main%20boolean%202.png
The Equals() method has two overloads for integers. We can see the System.Int32 struct in the following picture. The System.Int32 struct implements the IEquatable<T> interface. 

http://www.c-sharpcorner.com/UploadFile/91c28d/working-with-net-equality-features469/Images/namespace%20system%20yellow.png
IEquatable<T> is very useful to a value type.

Return to Top

See Also

.NET: Best Approach Implementing equality comparison