Boxed Value Type comparisons

本秂侑毒 提交于 2019-12-04 00:55:18

Looks like you are assuming the type from arg1 is the one you want to convert to, so I'd use a genric like this. As long as arg2 is IConvertible (int, double, all numerics, string, etc are all IConvertible) this will work:

public static bool ValueEquality<T1, T2>(T1 val1, T2 val2) 
    where T1 : IConvertible 
    where T2 : IConvertible
{
    // convert val2 to type of val1.
    T1 boxed2 = (T1) Convert.ChangeType(val2, typeof (T1));

    // compare now that same type.
    return val1.Equals(boxed2);
}

** UPDATE ** Made both types generic args, can both be inferred and adds more compile time safety on arg2 to make sure it's IConvertible at compile time.

Given this generic function, all of the following now return true (don't need to specify type argument since inferred from first argument:

        Console.WriteLine(ValueEquality(1, "1"));
        Console.WriteLine(ValueEquality(2, 2.0));
        Console.WriteLine(ValueEquality(3, 3L));

UPDATE

Based on your comment, here's an overload if all you have are objects. Both can co-exist and it will call the one more appropriate based on the arguments:

    public static bool ValueEquality(object val1, object val2)
    {
        if (!(val1 is IConvertible)) throw new ArgumentException("val1 must be IConvertible type");
        if (!(val2 is IConvertible)) throw new ArgumentException("val2 must be IConvertible type");

        // convert val2 to type of val1.
        var converted2 = Convert.ChangeType(val2, val1.GetType());

        // compare now that same type.
        return val1.Equals(converted2);
    }

And this will work for object:

        object obj1 = 1;
        object obj2 = 1.0;

        Console.WriteLine(ValueEquality(obj1, obj2));

As I said, both of these can co-exist as overloads, so if you compare compatible IConvertible types directly it will use the generic, and if you just have boxed types as object, it will use the object overload.

Look into using IComparable instead of manual if's - http://msdn.microsoft.com/en-us/library/system.icomparable.compareto.aspx.

If you need something similar in future consider swith on types of one operand first and implementing "operation handler" class for each of the types with method to handle the operation like IntOpHandler.PerformOp(int left, object right).

You can also often decrease number of types you need to deal with by merging multiple types togeter first (i.e. byte, short, ushort, int, uint, long - cast to long first, then perform operations on long).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!