This page contains general knowledge about the usage of Equals, IComparar and IComparable in C# Equals in C# can be used to compare advanced objects rather than just the value of an int or a string.

Examples of True and False Equals in C#

Value Type Comparisons

// True comparison with integers
int a = 5;
int b = 5;
bool result = a.Equals(b); // true - same value

// False comparison with integers
int c = 5;
int d = 10;
bool result2 = c.Equals(d); // false - different values

String Comparisons

// True comparison with strings
string str1 = "hello";
string str2 = "hello";
bool result = str1.Equals(str2); // true - same content

// False comparison with strings
string str3 = "hello";
string str4 = "world";
bool result2 = str3.Equals(str4); // false - different content

// Case-sensitive comparison (false)
string str5 = "Hello";
string str6 = "hello";
bool result3 = str5.Equals(str6); // false - different case

// Case-insensitive comparison (true)
bool result4 = str5.Equals(str6, StringComparison.OrdinalIgnoreCase); // true

Reference Type Comparisons

// Default behavior for reference types (comparing references, not content)
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

// False comparison - different references even with same content
Person person1 = new Person { Name = "John", Age = 30 };
Person person2 = new Person { Name = "John", Age = 30 };
bool result = person1.Equals(person2); // false - different objects in memory

// True comparison - same reference
Person person3 = person1;
bool result2 = person1.Equals(person3); // true - same object in memory

Overriding Equals for Custom Types

class Employee
{
    public string Name { get; set; }
    public int EmployeeId { get; set; }

    public override bool Equals(object obj)
    {
        // Check if null or different type
        if (obj == null || GetType() != obj.GetType())
            return false;

        // Cast to Employee
        Employee other = (Employee)obj;
        
        // Compare by EmployeeId
        return EmployeeId == other.EmployeeId;
    }

    // Always override GetHashCode when overriding Equals
    public override int GetHashCode()
    {
        return EmployeeId.GetHashCode();
    }
}

// Usage examples
Employee emp1 = new Employee { Name = "Alice", EmployeeId = 101 };
Employee emp2 = new Employee { Name = "Bob", EmployeeId = 101 };  
Employee emp3 = new Employee { Name = "Charlie", EmployeeId = 102 };

bool result1 = emp1.Equals(emp2); // true - same EmployeeId despite different Names
bool result2 = emp1.Equals(emp3); // false - different EmployeeId

Comparison of Equals vs Standard Comparison Operators

Here's a comparison between the Equals method and standard comparison operators in C#:

Feature Equals Method Standard Operators (==, !=, etc.)
Reference types Default compares references, can be overridden to compare values Compares references by default
Value types Compares values Compares values
Null handling Safer: obj.Equals(null) returns false without exceptions Can cause NullReferenceException if left operand is null
Polymorphism Can be overridden for customized comparison logic Operators can be overloaded but with limitations
String comparison Offers options like StringComparison.OrdinalIgnoreCase Basic comparison only, needs extra code for case insensitivity

IComparable and IComparer

Understanding IComparable and IComparer

Wanting to sort a list of numbers and or text is fairly easy in C# as this can be done automatically. Sorting a list of objects however is a different story as C# does not know by default which object property you wish to sort to accordingly. This is where IComparable<T> and and IComparar<T> comes in.

Using IComparable<T> means you allow your class to compare itself to other objects of the same type. This is done using the method called CompareTo. This method is what tells explains what is to be compared.