C# 比较两个对象的值

3

我目前有两个对象(相同类型),可以表示任何基本值,如字符串、整数、日期时间等。

var valueX = ...;
var valueY = ...;

目前我是按照字符串级别进行比较的,就像这样

var result = string.Compare(fieldValueX.ToString(), fieldValueY.ToString(), StringComparison.Ordinal);

但我需要按类型(如整数)进行比较。

int i = 0;
int j = 2;
i.CompareTo(j);

如果它们恰好是日期等类型,可以将它们作为日期处理等等。

object.Compare(x,y);

如何实现以相同的方式返回-1、0、1?


4
其中一个可以是null吗?如果不能,您可以使用 ((IComparable)x).CompareTo(y) - Lee
Object.Equal不起作用吗?它会返回一个bool而不是一个int - Hank
2
但我需要在类型级别上进行比较(如果它们恰好是整数,则为整数... 我不确定你在问什么。请检查对象是否实现了IComparable,将其转换为IComparable并执行比较。如果这不起作用,请包括一个最小完整可验证示例,以便更好地说明您的问题。 - Igor
5个回答

11

谢谢你的回答,正确的方法是检查对象是否实现了IComparable接口,如果实现了,则进行类型转换并调用CompareTo方法。

if (valueX is IComparable)
{
     var compareResult = ((IComparable)valueX).CompareTo((IComparable)valueY);
}

1

除非 @object 引用的是同一个对象,否则 Object1.Equals(obj1, obj2) 将无法工作。

例如:

var obj1 = new MyObject();
var obj2 = new MyObject();

这将对 Object1.Equals(obj1, obj2) 返回 "False",因为它们是不同的引用。
var obj1 = new MyObject();
var obj2 = obj1;

这将返回“True”对于Object1.Equals(obj1, obj2),因为它们是相同的引用。 解决方案: 您可能需要编写一个扩展方法来覆盖Object.Equals。可以为特定类型创建自定义对象比较器(请参见此处以获取自定义对象比较器:),或者可以动态地遍历每个属性并进行比较。

0

有几种方法可以实现这个。

覆盖 Object.Equal

您可以在类中覆盖 Object.Equal() 方法,然后确定对象何时相等。这也可以让您巧妙地决定要比较什么,因为这些对象似乎可以是多个数据类型。在此覆盖中,您需要处理每种可能的情况。您可以在此处阅读更多关于此选项的信息:

https://msdn.microsoft.com/en-us/library/bsc2ak47(v=vs.110).aspx

需要注意的是,默认情况下,Object.Equal()将比较您对象的引用。

实现IComparable

IComparable是一个很好的接口,它为对象提供了Compare。正如注释所述,这将让您根据任何标准定义如何比较对象。

此选项在此处得到了涵盖:https://msdn.microsoft.com/en-us/library/system.icomparable(v=vs.110).aspx

实现CompareBy()方法

或者,您可以为每种可能的类型实现方法,例如CompareByInt()CompareByString(),但这种方法取决于您在进行操作时知道将要使用什么。这也会对代码的维护造成负面影响,因为涉及到更多的方法。


0
将对象转换为字典,然后按照数学集合的概念进行减法运算,结果项应为空,以防它们是相同的。
public static IDictionary<string, object> ToDictionary(this object source)
    {
        var fields = source.GetType().GetFields(
            BindingFlags.GetField |
            BindingFlags.Public |
            BindingFlags.Instance).ToDictionary
        (
            propInfo => propInfo.Name,
            propInfo => propInfo.GetValue(source) ?? string.Empty
        );

        var properties = source.GetType().GetProperties(
            BindingFlags.GetField |
            BindingFlags.GetProperty |
            BindingFlags.Public |
            BindingFlags.Instance).ToDictionary
        (
            propInfo => propInfo.Name,
            propInfo => propInfo.GetValue(source, null) ?? string.Empty
        );

        return fields.Concat(properties).ToDictionary(key => key.Key, value => value.Value); ;
    }
    public static bool EqualsByValue(this object source, object destination)
    {
        var firstDic = source.ToFlattenDictionary();
        var secondDic = destination.ToFlattenDictionary();
        if (firstDic.Count != secondDic.Count)
            return false;
        if (firstDic.Keys.Except(secondDic.Keys).Any())
            return false;
        if (secondDic.Keys.Except(firstDic.Keys).Any())
            return false;
        return firstDic.All(pair =>
          pair.Value.ToString().Equals(secondDic[pair.Key].ToString())
        );
    }
    public static bool IsAnonymousType(this object instance)
    {

        if (instance == null)
            return false;

        return instance.GetType().Namespace == null;
    }
    public static IDictionary<string, object> ToFlattenDictionary(this object source, string parentPropertyKey = null, IDictionary<string, object> parentPropertyValue = null)
    {
        var propsDic = parentPropertyValue ?? new Dictionary<string, object>();
        foreach (var item in source.ToDictionary())
        {
            var key = string.IsNullOrEmpty(parentPropertyKey) ? item.Key : $"{parentPropertyKey}.{item.Key}";
            if (item.Value.IsAnonymousType())
                return item.Value.ToFlattenDictionary(key, propsDic);
            else
                propsDic.Add(key, item.Value);
        }
        return propsDic;
    }
originalObj.EqualsByValue(messageBody); // will compare values.

代码来源


0

您可以编写一个带有必要的重载的Compare方法的GeneralComparer

对于必须执行标准比较的类型,您可以使用EqualityComparer<T>.Default;对于其他类型,您可以编写自己的比较函数。以下是一个示例:

static class GeneralComparer
{
    public static int Compare(int x, int y)
    {
        //for int, use the standard comparison:
        return EqualityComparer<int>.Default.Equals(x, y);
    }

    public static int Compare(string x, string y)
    {
        //for string, use custom comparison:
        return string.Compare(x, y, StringComparison.Ordinal);
    }

    //overload for DateTime
    //overload for MyType
    //overload for object
    //...
}

正确的重载在运行时被选择。

缺点是:如果您将两个int(或其他特定类型)声明为对象,则会调用对象重载:

object a = 2;
object b = 3;
//this will call the "Compare(object x, object y)" overload!
int comparison = GeneralComparer.Compare(a, b); 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接