C# Compare two object values

时间:2016-10-20 13:11:09

标签: c# .net

I currently have two objects (of the same type) that may represent any primitive value such as string, int, datetime etc.

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

Atm I compare them on string level like this

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

But I need to compare them on type level (as ints if those happen to be ints

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

, as dates if they happen to be date etc), something like

object.Compare(x,y);

That returns -1,0,1 in the same way. What are the ways to achieve that ?

5 个答案:

答案 0 :(得分:8)

感谢您的回答,正确的方法是检查对象是否实现IComparable,如果是,请进行类型转换并调用CompareTo

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

答案 1 :(得分:0)

There's several options to do this.

Override Object.Equal

You can override the Object.Equal() method in the class, and then determine what makes the objects equal there. This can also let you cleverly decide what to compare, since it appears those objects can be multiple data types. Inside this override, you'll need to handle each possible case. You can read more about this option here:

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

It should be noted by default, Object.Equal() will compare your objects references.

Implement IComparable

IComparable is a neat interface that gives an object Compare. As the comments mention, this will let you define how to compare the objects based on whatever criteria you want.

This option gets covered here: https://msdn.microsoft.com/en-us/library/system.icomparable(v=vs.110).aspx

Implement CompareBy() Methods

Alternatively, you can implement methods for each possible type, ie CompareByInt() or CompareByString(), but this method depends on you knowing what you're going to have when you go to do it. This will also have the negative effect of making code more difficult to maintain, as there's many more methods involved.

答案 2 :(得分:0)

Object1.Equals(obj1,obj2)不会工作,除非@object引用同一个对象。

<强> EG:

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

这将为Object1.Equals(obj1, obj2)返回“False”,因为它们是不同的参考

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

这将为Object1.Equals(obj1, obj2)返回“True”,因为它们是相同的参考号。

<强>解决方案: 您很可能需要编写一个覆盖Object.Equals的扩展方法。为特定类型(See here for custom object comparer:)创建自定义对象比较器,或者您可以动态浏览每个属性并进行比较。

答案 3 :(得分:0)

您可以使用GeneralComparer方法编写Compare,并根据需要进行重载。 对于必须执行标准比较的类型,您可以使用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,则会调用 object 重载:

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

答案 4 :(得分: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.

source of the code