Miral
Miral

Reputation: 79

Generically compare two objects

A naive question I know and after two years of experience I am stuck to answer it.

Simply I need to create a generic method and this method may take int, double, float and compare them and find the bigger value:

object ComapreMethod(object obj1, object obj2)
{ 
    if(obj1 > obj2)
    {
        return obj1;
    }

    return obj2;
}

I want to call it for the int,short,ushort,float,double,...etc what I am really stuck with how to compare between obj1 and obj2 I can't write it by the way above I know it is naive but I dunno it

Upvotes: 4

Views: 1495

Answers (4)

Mohamad Shiralizadeh
Mohamad Shiralizadeh

Reputation: 8765

you can do it using reflection. I get the type of first one and get the CompareTo method and run it:

void Main()
{
    float a = 2;
    float b = 1;
    ComapreMethod(a, b); // A > B

    short c = 0;
    short d = 3;
    ComapreMethod(c, d); // A < B

    int e = 1;
    int f = 1;
    ComapreMethod(e, f); // A == B
}

// you can change the return type as you wish
string ComapreMethod(object a, object b)
{ 
    var result = Convert.ToInt32(a.GetType().GetMethods().First(o => o.Name == "CompareTo").Invoke(a, new object[] { b }));

    if (result == 0)
        return "A == B";
    else if (result > 0)
        return "A > B";
    else if (result < 0)
        return "A < B";
    else
        return "I don't know...";
}

Upvotes: 0

mybirthname
mybirthname

Reputation: 18127

I will suppose that you will need to compare two different types. Example int and decimal.

    static void Main(string[] args)
    {
        decimal p = 15.5m;
        int q = 5;

        Console.WriteLine(CompareTo<int, decimal, decimal>(q, p));

    }

    public static T3 CompareTo<T1, T2, T3>(T1 value1, T2 value2) 
        where T3:IComparable
    {
        T3 p = ConvertTo<T3>(value1);
        T3 q = ConvertTo<T3>(value2);

        if(p.CompareTo(q) >= 0)
        {
            return p;
        }
        else
        {
            return q;
        }
    }

    public static T ConvertTo<T>(object value)
    {
        try
        {
            return (T)Convert.ChangeType(value, typeof(T), CultureInfo.InvariantCulture);
        }
        catch(Exception ex)
        {
            return (T)(typeof(T).IsValueType ? Activator.CreateInstance(typeof(T)) : null);
        }

    }

T1 is your first value type, T2 is your second value type which you will compare, T3 will be the result type which you are expecting( decimal, double etc.).

Upvotes: 1

Chris
Chris

Reputation: 27609

There is a builtin solution that will do what you want, Math.Max (MSDN docs):

var myMax = Math.Max(input1, input2);

This will work for any different types input1 and input2 that can be implicitly converted to the same type. So you can interchangeably use int, float and double and it will return the appropriate value in the appropriate type (eg if passing an int and a double it will return a double)).

You could also if you wanted to just modify your method to accept doubles if you wanted to:

double CompareMethod(double obj1, double obj2) 
{
    if (obj1.CompareTo(obj2) > 0)
    {
        return obj1;
    }
    return obj2;
}

This again uses implicit type conversion to make ints into doubles, etc. This would mean that your return type is always a double but if you wanted to ints to return and int you can create overloads and the compiler should choose the best one.

Personally though I advise you to just use the built in

Upvotes: 4

Andrey Korneyev
Andrey Korneyev

Reputation: 26856

Well, you can change your method signature using generics:

TType ComapreMethod<TType>(TType obj1, TType obj2) where TType : IComparable

and change your code in method from if(obj1>obj2) to if (obj1.CompareTo(obj2) > 0) (and don't forget to handle cases of obj1 and obj2 being null).

In this case you will be able to pass to your method values of some class that implemented IComparable interface, including ints, doubles and floats.

Upvotes: 8

Related Questions