Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficient Object Equality C#

Tags:

c#

I am trying to improve performance on the following (sample) code.

Object[] inputKeys = new Object[10];
inputKeys[0] = "4021";
inputKeys[1] = "3011";
inputKeys[2] = "1010";
inputKeys[3] = "1020";
inputKeys[4] = "1030";

then the input keys are compared.

for (int i = 0; i < 5; i++)
{
    for (int j = 0; j < 5; j++)
    {
        bool result = inputKeys[i].Equals(inputKeys[j]);
    }
}

The inputKeys can be all of type string, int32 or DateTime.

There is a huge performance drop in .Equals line, when it hits millions of times.

Any suggestions on how to improve performance of this line (the equality check)?

I have tried this: Using an array of below class instead of the Object array to hold the keys. There I keep the Key type and key values.

public class CustomKey : IEquatable<CustomKey>{
    internal int KeyType { get; private set; }

    internal string ValueString { get; private set; }
    internal int ValueInteger { get; private set; }
    internal DateTime ValueDateTime { get; private set; }

    internal CustomKey(string keyValue)
    {
        this.KeyType = 0;
        this.ValueString = (string)keyValue;
    }

    internal CustomKey(int keyValue)
    {
        this.KeyType = 1;
        this.ValueInteger = (int)keyValue;
    }

    internal CustomKey(DateTime keyValue)
    {
        this.KeyType = 2;
        this.ValueDateTime = (DateTime)keyValue;
    }

    public bool Equals(CustomKey other)
    {
        if (this.KeyType != other.KeyType)
        {
            return false;
        }
        else
        {
            if (this.KeyType == 0)
            {
                return this.ValueString.Equals(other.ValueString);
            }
            else if (this.KeyType == 1)
            {
                return this.ValueInteger.Equals(other.ValueInteger);
            }
            else if (this.KeyType == 2)
            {
                return this.ValueDateTime.Equals(other.ValueDateTime);
            }
            else
            {
                return false;
            }
        }
    }
}

But the performance was worse.

like image 794
Gayan Dasanayake Avatar asked Dec 18 '12 17:12

Gayan Dasanayake


2 Answers

Your comparison loop is inefficient. I suggest you to try to use:

Distinct<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)

Define your IEqualityComparer for that type and pass it to that method. You won't get a bool, but you're going to get an IEnumerable containing the list without duplicates.

like image 189
Mir Avatar answered Oct 06 '22 06:10

Mir


As an example of algorithm efficiency, your first code could be rewritten

for (int i = 0; i < 5; i++)
{
    for (int j = i; j < 5; j++)
    {
        bool result = inputKeys[i].Equals(inputKeys[j]);
    }
}

because x.Equals(y) will give the same results as y.Equals, you don't need to check both ways. http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx

The new implementation of Equals should follow all the guarantees of

x.Equals(y) returns the same value as y.Equals(x).

like image 37
hatchet - done with SOverflow Avatar answered Oct 06 '22 07:10

hatchet - done with SOverflow