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

是否有可能在C#中使用它们的types比较器比较两个未知types的对象(包括引用types和值types)是否存在?

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

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, ie: 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 

有没有一个通用的方法来解决这个问题,将适用于任何types的对象?

你可以使用静态的object.Equals(object x, object y)方法,而不用费神写你的方法。 这将适当地处理空值,并委托到与xy有关的object.Equals(object)的实现…它应该无关紧要,因为Equals意味着是对称的。

请注意,这不会为任何types使用==运算符 – 操作符不能被重载,只会被重载(这意味着它们是在编译时select的,而不是在执行时select的 。在大多数情况下, Equals应该做你想做的在某些情况下,即使Equals被覆盖,==也不会被重载…但是我从来不知道任何types的对象都是真的。

请注意,使用这种方法将框中的任何值types…

编辑:删除部分有关重新实施 – 很差 – EqualityComparer<T>.Default 。 请参阅Marc的更多答案。 当然,如果你不能使用genericstypes,这将无济于事。

最后一点:我不会打电话给你的方法Compare 。 这个名字通常与sorting值相关,而不是比较它们是否相等。

一个合理的select是使用generics,即

 public bool Compare<T>(T a, T b) {...} 

您不需要在您的代码中指定T ,因为编译器通常能够将其解决(即您现有的样本将按原样工作)

为了执行:

 bool equal = EqualityComparer<T>.Default.Equals(x, y); 

(对于通用typesT

实际上我会避免Compare ,因为这是其他地方使用意味着< / == / > – 所以我可能有:

 public static bool Equals<T>(T a, T b) { return EqualityComparer<T>.Default.Equals(a, b); } 

这个:

  • 当T是一个结构体时避免装箱
  • 正确处理null / Nullable<T>
  • 支持IEquatable<T>
  • 或回落到正常的Equals

它不使用==运算符,但MiscUtil有一个Operator类, 通过

 bool equal = Operator.Equal<T>(x,y); 

(注意,如果T没有==运算符,则后者将会失败,但考虑到它,可以使用EqualityComparer<T>.Default.Equals作为后备;它不会)


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

如何object.equals(x, y) ? 这也将接受空值。

关于什么

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

我不能100%确定这是否适用于所有情况,但请试一试

 public bool比较(对象a,对象b)
 {
     (b);
 }