盒装值类型比较
我在这里试图实现的是盒装原始类型的直接值比较。
((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)
我明白‘为什么’。我只是没有看到“如何”。
这些类型在运行时之前是未知的,它们可以是来自数据源的任何原始类型。其中包括字符串、日期时间、布尔值等。 我已经沿着丑陋的路线编写了一个扩展方法来计算两种类型,然后在进行“==”比较之前进行强制转换:(为了完整性,我包含了每个原始类型,加上我感兴趣的类型
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 多行长,这很好(但很可怕),但现在我需要做的不仅仅是“==”。我需要 >、<、<=、>=、!=。
Reflection 中有什么东西可以用于盒装值类型比较吗?
有什么吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
看起来您假设 arg1 中的类型是您想要转换为的类型,所以我会使用这样的通用类型。只要 arg2 是 IConvertible(int、double、所有数字、字符串等都是 IConvertible),这就可以工作:
** 更新 ** 将两种类型设为通用 args,都可以推断,并在 arg2 上添加更多编译时安全性,使确保它在编译时是 IConvertible。
给定这个通用函数,以下所有内容现在都返回 true (不需要指定类型参数,因为从第一个参数推断出:
UPDATE
根据您的评论,如果您拥有的只是对象,那么这里是一个重载。两者可以共存,并且它会根据参数调用更合适的一个:
这将适用于对象:
正如我所说,这两者都可以作为重载共存,因此如果您直接比较兼容的 IConvertible 类型,它将使用通用的,如果你只要将装箱类型作为对象,它将使用对象重载。
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:
** 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:
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:
And this will work for object:
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.
考虑使用 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,然后对 long 执行操作)。
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).