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

Dua*_*ane 38 .net c#

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

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

public bool Compare(object a, object b)
{
     // compare logic goes here
}
Run Code Online (Sandbox Code Playgroud)

哪会回来

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
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*eet 63

你可以使用静态object.Equals(object x, object y)方法而不用费心去编写你的方法.这将适当地处理空值,并委托给object.Equals(object)与之相关联的实现x或者y...它应该无关紧要,因为Equals它是对称的.

请注意,这不会对任何类型使用==运算符 - 运算符不能被重写,只能重载(这意味着它们是在编译时选择的,而不是执行时.在大多数情况下Equals应该按照您的意愿执行.在某些情况下,即使Equals被覆盖,==也可能不会超载...但我从来不知道在我使用的任何类型中反之亦然.

请注意,使用此方法将包装任何值类型...

编辑:删除了关于有效重新实现的部分 - 很差 - EqualityComparer<T>.Default.请参阅Marc的答案.如果你不能使用通用类型,这对你没有帮助.

最后一点:我不会打电话给你的方法Compare.该名称通常与排序值相关联,而不是将它们进行相等性比较.


Mar*_*ell 20

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

public bool Compare<T>(T a, T b) {...}
Run Code Online (Sandbox Code Playgroud)

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

为实施:

bool equal = EqualityComparer<T>.Default.Equals(x, y);
Run Code Online (Sandbox Code Playgroud)

(对于通用类型T)

实际上我会避免使用这个词Compare,因为这在其他地方用来表示</ ==/ >- 所以我可能会:

public static bool Equals<T>(T a, T b) {
    return EqualityComparer<T>.Default.Equals(a, b);
}
Run Code Online (Sandbox Code Playgroud)

这个:

  • 当T是结构时避免装箱
  • 处理空值/ Nullable<T>正确
  • 支持 IEquatable<T>
  • 或者回到常规 Equals

它并没有使用==运营商,但MiscUtil有一个Operator类,它通过

bool equal = Operator.Equal<T>(x,y);
Run Code Online (Sandbox Code Playgroud)

(注意如果T没有==运算符,后者将失败,虽然考虑它,它可以EqualityComparer<T>.Default.Equals用作后备;它只是没有)


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


Blu*_*doo 5

怎么样object.equals(x, y)?这也将接受空值.