Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In c#, what is the difference between equality members and an equality comparer, and which should you use?

Please explain the difference between C# equality members and an equality comparer, and how to choose which one is required, and in what circumstances they are used?

I am particularly interested in which are required for LINQ operations or other language built in comparisons within .NET operations or types - for example, Dictionary keys.

Thank you.

like image 925
Aalawlx Avatar asked Sep 18 '14 22:09

Aalawlx


1 Answers

Assumption - C# equality members - ex. Equals(...) method. c# Equality Comparer - e.g.. IEqualityComparer interface.

In short answer is with the help of Equality Compare you can increase usability of your code.

For e.g. You are Building a catalog of vehicles and you want to make sure that the key, which is model number and code are not same. Now this logic is for any kind of Vehicles. Thus, it is a good idea to define a default comparer and use it everywhere.

Here is an example for your reference:

using System;
using System.Collections.Generic;
using ConsoleApplication3;

public class Program
{
    internal class Car : IVehicle
    {
        public List<string> Features { get; set; }
        public string ModelNumber { get; set; }
        public string ModelCode { get; set; }
    }

    internal class Bike : IVehicle
    {
        public string ModelNumber { get; set; }
        public List<string> Features { get; set; }
        public string ModelCode { get; set; }
    }

    public static void Main()
    {
        var carCatelogue = new Dictionary<Car, int>(new GlobalEqualityComparer());
        var bikeCatelogue = new Dictionary<Bike, int>(new GlobalEqualityComparer());

        carCatelogue.Add(new Car()
        {
            ModelCode = "100",
            ModelNumber = "CAR-01",
            Features = new List<string> { "BEST ENGINE", "5 GEAR", "SPOTY" }
        }, 5);

        carCatelogue.Add(new Car()
        {
            ModelCode = "100",
            ModelNumber = "CAR-02",
            Features = new List<string> { "SUPER FAST ENGINE", "4 GEAR", "SPOTY RED" }
        }, 10);

        // This Statement will throw exception because car-02 key already exists.
        carCatelogue.Add(new Car()
        {
            ModelCode = "100",
            ModelNumber = "CAR-02",
            Features = new List<string> { "SUPER FAST ENGINE", "4 GEAR", "SPOTY RED" }
        }, 10);

        bikeCatelogue.Add(new Bike()
        {
            ModelCode = "200",
            ModelNumber = "BIK-01",
            Features = new List<string> { "800 CC", "10 GEAR", "SPOTY BLACK" }
        }, 5);


        // this will throw exception because the key is aleady exists.
        bikeCatelogue.Add(new Bike()
        {
            ModelCode = "200",
            ModelNumber = "BIK-01",
            Features = new List<string> { "800 CC", "10 GEAR", "SPOTY BLACK" }
        }, 5);
    }

    private class GlobalEqualityComparer : IEqualityComparer<IVehicle>
    {
        public bool Equals(IVehicle x, IVehicle y)
        {
            return x.ModelNumber.Equals(y.ModelNumber, StringComparison.CurrentCultureIgnoreCase)
            && x.ModelCode.Equals(y.ModelCode, StringComparison.CurrentCultureIgnoreCase);
        }

        public int GetHashCode(IVehicle obj)
        {
            return string.Format("{0}{1}", obj.ModelCode, obj.ModelNumber).GetHashCode();
        }
    }
}

In case of using members such as equals, you will have to write the same logic for Car, as well as Bike.

Now when you would like to use where, it will completely comes down to you.

If you are happy with base Equal i.e. compare Reference to reference vs. Value to value, then you can stay with it and you don't need to override.

If you are specific to any question, you need to give me an example.

Hope it helps.

like image 134
codebased Avatar answered Sep 28 '22 10:09

codebased