盒装值类型比较
本文关键字:比较 类型 盒装 | 更新日期: 2023-09-27 18:01:48
我想在这里实现的是盒装基本类型的直接值比较。
((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)
我明白"为什么"。我只是不知道怎么做。
类型在运行时之前是未知的,它们可以是来自数据源的任何基本类型。这包括字符串、日期时间、bool等。我已经走了一条丑陋的路线,编写了一个扩展方法来计算这两种类型,然后在进行'=='比较之前进行类型转换:(为了完整,我包括了所有基本类型,以及我感兴趣的那些)
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 ...>
生成的方法有300多行,这很好(但很难看),但是现在我需要做的不仅仅是'=='。我需要>,<, <=,>=, !=.
有什么在反射,我可以使用盒装值类型比较?
有什么事吗?
看起来您假设arg1的类型是您想要转换的类型,因此我将使用这样的泛型。只要arg2是不可转换的(int, double,所有数字,字符串等都是不可转换的),这就可以工作:
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 **使这两种类型都是泛型参数,都可以被推断,并在arg2上增加了更多的编译时安全性,以确保它在编译时是不可转换的。
给定这个泛型函数,下面所有的现在都返回true(不需要指定类型参数,因为从第一个参数推断:
Console.WriteLine(ValueEquality(1, "1"));
Console.WriteLine(ValueEquality(2, 2.0));
Console.WriteLine(ValueEquality(3, 3L));
根据你的评论,如果你所有的都是对象,这是一个重载。两者可以共存,它将根据参数调用更合适的一个:
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);
}
这将适用于object:
object obj1 = 1;
object obj2 = 1.0;
Console.WriteLine(ValueEquality(obj1, obj2));
正如我所说的,这两种类型都可以作为重载共存,所以如果你直接比较兼容的IConvertible类型,它将使用泛型,如果你只是把盒装类型作为对象,它将使用对象重载。
考虑使用IComparable代替手动if - http://msdn.microsoft.com/en-us/library/system.icomparable.compareto.aspx.
如果你将来需要类似的东西,考虑先切换一个操作数的类型,并为每个类型实现"操作处理程序"类,并提供处理操作的方法,如IntOpHandler.PerformOp(int left, object right)
。
您还可以通过先合并多个类型来减少需要处理的类型数量(例如,byte, short, ushort, int, uint,先将其转换为long类型,然后对long类型执行操作)。