C#比较两个未知类型的对象(包括引用和值类型)

C#比较两个未知类型的对象(包括引用和值类型),c#,.net,C#,.net,在C#中,如果存在两个未知类型的对象(包括引用类型和值类型),是否可以使用它们的类型比较器来比较它们 目标是编写一个具有如下签名的函数: public bool Compare(object a, object b) { // compare logic goes here } 哪个会回来 Compare(100d, 100d) == true Compare(100f, 100f) == true Compare("hello", "hello") == true Compare(

在C#中,如果存在两个未知类型的对象(包括引用类型和值类型),是否可以使用它们的类型比较器来比较它们

目标是编写一个具有如下签名的函数:

public bool Compare(object a, object b)
{
     // compare logic goes here
}
哪个会回来

Compare(100d, 100d) == true
Compare(100f, 100f) == true
Compare("hello", "hello") == true
Compare(null, null) == true 
Compare(100d, 101d) == false
Compare(100f, null) == false

// Use type comparators where possible, i.e.:
Compare(new DateTime(2010, 12, 01), new DateTime(2010, 12, 01)) == true
Compare(new DateTime(2010, 12, 01), new DateTime(2010, 12, 02)) == false
Compare(new DateTime(2010, 12, 01), null) == false
是否有一种通用方法可以解决任何类型的对象的问题?

如何

if (a == null && b == null) return true;
if (a == null && b != null) return false;
return (a.equals(b));

那么
object.equals(x,y)
呢?这也将接受空值。

我不能100%确定这是否在所有情况下都有效,但请尝试一下

public bool Compare(object a, object b) { return a.Equals(b); } 公共布尔比较(对象a、对象b) { 返回a等于(b); }
您可以使用static
object.Equals(object x,object y)
方法,而无需编写方法。这将适当地处理空值,并委托给与
x
y
关联的
object.Equals(object)
的实现。。。当
等于
时,哪一个应该是对称的并不重要

请注意,这不会对任何类型使用==运算符-运算符不能被重写,只能重载(这意味着它们是在编译时选择的,而不是在执行时选择的。在大多数情况下,
Equals
应该做您想做的事情。在某些情况下,==可能不会重载,即使
Equals
被重写……但我从未知道在我使用过的任何类型中都会出现相反的情况

请注意,使用此方法将框选任何值类型

编辑:删除了关于有效重新实现的部分-糟糕-
EqualityComparer.Default
。有关更多信息,请参阅Marc的答案。当然,如果您不能使用泛型类型,这对您没有帮助


最后一点:我不会调用您的方法
Compare
。该名称通常与排序值关联,而不是对它们进行相等性比较。

一个合理的选择是使用泛型,即

public bool Compare<T>(T a, T b) {...}
(对于泛型
T

但实际上,我会避免使用“比较”
,因为在其他地方它的意思是
,所以我可能会:

public static bool Equals<T>(T a, T b) {
    return EqualityComparer<T>.Default.Equals(a, b);
}
(注意,如果
T
没有
=
运算符,则后者将失败,尽管考虑到它,它可以使用
EqualityComparer.Default.Equals
作为回退;它只是没有)



为了完整性,请注意
Comparer.Default.Compare(x,y)
处理比较操作。

如果a为null,这将导致NullReferenceException。后者肯定只适用于引用类型,因为必须使用
其中T:class
,才能使用
v1==null
,从而防止值类型比较。是否有任何不使用
EqualityComparer.Default
的原因t会使事情变得更一般(
IEquatable
约束不是必需的),但除非绝对必要,否则不会强制装箱,不是吗?@aqwert:Nope。对于值类型,它总是计算为null。@Ani:只是大脑冻结:)Marc现在已经在他的答案中涵盖了这一点,所以我编辑了我的内容。有没有办法让它也适用于原始类型,如int、long等。感谢您的出色回答,您自己和Jon Skeet的答案都适用于我的特定用例。
public static bool Equals<T>(T a, T b) {
    return EqualityComparer<T>.Default.Equals(a, b);
}
bool equal = Operator.Equal<T>(x,y);