4

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

Miral
  • 79
  • 11
  • 4
    Better go for `Generics`. – Rahul Singh Dec 29 '14 at 12:41
  • I don't understand what you mean – Miral Dec 29 '14 at 12:42
  • possible duplicate of [C# generics: How to compare values of generic types?](http://stackoverflow.com/questions/6480577/c-sharp-generics-how-to-compare-values-of-generic-types) – Bob. Dec 29 '14 at 12:44
  • 1
    What do you want to do if the data types are different? eg is just converting all of them to double and then comparing acceptable? And the usual way when writing comparison functions is to return a value that indicates which is bigger or smaller rather than returning the biggest one immediately. see http://msdn.microsoft.com/en-us/library/System.IComparable(v=vs.110).aspx for an example of what I mean. – Chris Dec 29 '14 at 12:44
  • Use Expression.GreaterThan :)) – dev hedgehog Dec 29 '14 at 13:17
  • Check my answer if you want to compare 2 different types. In this case this is not duplicate ! – mybirthname Dec 29 '14 at 13:20

4 Answers4

8

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.

Andrey Korneyev
  • 26,353
  • 15
  • 70
  • 71
  • How you will compare int and decimal with this method ? – mybirthname Dec 29 '14 at 13:02
  • @mybirthname Well, in the OP's question it was not specified explicitly that he wants to mix different types in comparison. – Andrey Korneyev Dec 29 '14 at 13:09
  • Let's see what is the goal, I'm pretty sure that he wants to compare different types. – mybirthname Dec 29 '14 at 13:12
  • 1
    I wrote how to compare 2 diffeernt types. – mybirthname Dec 29 '14 at 13:23
  • 1
    Implicit conversion means that if you call this with a decimal and an int it will just convert the int to a decimal so this works fine with the types given even if they are mixed up (which I have to admit is how I read it as needed but may be wrong). – Chris Dec 29 '14 at 14:42
  • @Chris yes this will convert it always to int, which is probably not the desire of the OP. I wrote how to convert to compare different types, but your solution with Math.Max is may be the best. At least it covers almost everything. – mybirthname Dec 29 '14 at 14:46
  • @mybirthname: errr..., no. It will convert to the most suitable type. If you pass a double and an int it will convert the int to a double and consider `TType` to be `double` (because an int can convert to a double but a double won't become an int). Right some tests and play with it yourself (I did this because I had the same doubts that you did initially and wanted to test if it would convert). Its exactly the same as having a method with signature `(double obj1, double obj2)` effectively. – Chris Dec 29 '14 at 14:50
  • 1
    yes, yes I wrote about my example which is stupid ... :) Probably I should be more accurate. – mybirthname Dec 29 '14 at 14:51
  • 1
    I will agree that in this case Math.Max is best though. It is possible that the OPs situation is more complex and that the process involved is a little more complex though so other answers are helpful for those situations. :) – Chris Dec 29 '14 at 14:53
  • I don't want to add more classes in the tool – Miral Dec 30 '14 at 07:15
  • @Miral what "more" classes are you talking about? This is just change of your method to be generic. – Andrey Korneyev Dec 30 '14 at 07:18
  • I mean to add the TType class (which will implement the interface) can I do use object only – Miral Dec 30 '14 at 07:23
  • @Miral you don't need to add any class. `TType` is type parameter in declaration of generic method `ComapreMethod`. And this method should be called like `CompreMethod(x, y)` where x and y are floats and so on. Read [C# programming guide](http://msdn.microsoft.com/en-us/library/0zk36dx2.aspx) for reference about generics and how to use them. – Andrey Korneyev Dec 30 '14 at 07:36
4

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

Chris
  • 27,210
  • 6
  • 71
  • 92
1

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.).

mybirthname
  • 17,949
  • 3
  • 31
  • 55
0

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...";
}
Mohamad Shiralizadeh
  • 8,329
  • 6
  • 58
  • 93