装箱的值类型比较 [英] Boxed Value Type comparisons

查看:182
本文介绍了装箱的值类型比较的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么,我想在这里实现的是盒装的原始类型的直值比较。

 ((对象)12 ).Equals((对象)12); //类型匹配将导致一个值比较,
((对象)12).Equals((对象)12D); //但类型不匹配不会。 (假)
的Object.Equals((对象)12,(对象)12D); // 同样在这里。 (假)



我理解的'为什么'。我只是不明白一个如何。



的类型是未知的,直到运行时,在那里他们可以从一个数据源的基本类型。这包括字符串,日期时间,布尔变量等
我已经写下来的作品出两种类型,然后做一个==比较之前投下扩展方法丑陋的路线:(为了完整起见,我包括所有的基本类型,再加上那些我感兴趣的)

 公共静态布尔ValueEquals(此对象thisObj,对象进行比较)
{
如果(thisObj为int)
{
INT OBJ =(INT)thisObj;
如果(比较类型为int)
回报率(OBJ ==(INT)比较);
如果(Compare是UINT)
回报率(OBJ ==(UINT)比较);
如果(Compare是十进制)
回报率(OBJ ==(十进制)比较);
如果(Compare是浮动)
回报率(OBJ ==(浮点)比较);
< ...等等每一个原始类型...>
}
如果(thisObj是UINT)
{
UINT OBJ =(UINT)thisObj;
如果(比较类型为int)
回报率(OBJ ==(INT)比较);
如果(Compare是UINT)
回报率(OBJ ==(UINT)比较);
< ...再为每个原始类型...>
}
如果(thisObj为十进制)
{
十进制的obj =(十进制)thisObj;
如果(比较类型为int)
回报率(OBJ ==(INT)比较);
< ......等等,等等...>

生成的方法竟然是300多线长,这是很好的(但可怕的),但现在我需要做的不仅仅是'=='更多。我需要>,<中,<!=,> =,=



有没有思考什么,我可以用装箱值类型比较

了什么呢?


解决方案

看起来像我们假定你是从ARG1类型是要转换的一个,所以我会用这样的genric。只要Arg2为IConvertible(INT,双,所有的数字,字符串等都是IConvertible),这将工作:

 公开静态布尔ValueEquality< T1,T2>(T1 VAL1,T2将val2)
,其中T1:IConvertible
,其中T2:IConvertible
{
//转换val2的类型为VAL1的。
T1 boxed2 =(T1)Convert.ChangeType(val2中的typeof(T1));

//现在比较,相同的类型。
返回val1.Equals(boxed2);
}



**更新**制造两种类型的通用指定参数时,既可以推断和增加了更多的汇编ARG2时的安全,以确保它是IConvertible在编译时。



鉴于这种通用功能,所有的现在下返回true(不需要指定因为从第一个参数推断类型参数:

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

更新



根据您的意见,这里的过载,如果你已经有对象,两者可以并存

 公共静态布尔ValueEquality(对象VAL1,对象将val2)$ b:它会根据参数调用更为合适$ b {
如果((VAL1是IConvertible)!)抛出新的ArgumentException(VAL1必须是IConvertible类型);(!(val2的是IConvertible))
如果抛出新的ArgumentException(val2的必须是IConvertible类型);

//转换为val2的类型VAL1的。
变种converted2 = Convert.ChangeType(val2中,val1.GetType());

//现在比较,相同的类型。
返回val1.Equals(converted2);
}

和这会为对象的工作:

 目标OBJ1 = 1; 
对象OBJ2 = 1.0;

Console.WriteLine(ValueEquality(OBJ1,OBJ2));

正如我所说的,这两个可以共存的过载,因此,如果您比较兼容IConvertible类型直接它将使用通用的,如果你只是有盒装类型为研究对象,将使用该对象重载。


What i'm trying to achieve here is a straight value comparison of boxed primitive types.

((object)12).Equals((object)12); // Type match will result in a value comparison,
((object)12).Equals((object)12d); // but a type mismatch will not. (false)
object.Equals((object)12,(object)12d); // Same here. (false)

I understand the 'why'. I just don't see a 'how'.

The types are unknown until runtime, where they could be any primitive type from a datasource. That includes strings, datetimes, bools, etc. I've gone down the ugly route of writing an extension method that works out both types, and then casts before doing a '==' comparison: (For completeness, i included every primitive type, plus those i was interested in)

public static bool ValueEquals(this object thisObj, object compare)
    {
        if (thisObj is int)
        {
            int obj = (int)thisObj;
            if (compare is int)
                return (obj == (int)compare);
            if (compare is uint)
                return (obj == (uint)compare);
            if (compare is decimal)
                return (obj == (decimal)compare);
            if (compare is float)
                return (obj == (float)compare);
            <... and so on for each primitive type ...>
        }
        if (thisObj is uint)
        {
            uint obj = (uint)thisObj;
            if (compare is int)
                return (obj == (int)compare);
            if (compare is uint)
                return (obj == (uint)compare);
            <... Again for each primitive type ...>
        }
        if (thisObj is decimal)
        {
            decimal obj = (decimal)thisObj;
            if (compare is int)
                return (obj == (int)compare);
            <... Etc, etc ...>

The resulting method turned out to be 300+ lines long, which was fine (yet hideous), but now I need to do more than just '=='. I need >, <, <=, >=, !=.

Is there anything in Reflection that i could use for boxed value type comparisons?

Anything at all?

解决方案

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.

这篇关于装箱的值类型比较的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆