如何检查两个对象的属性是否相等

时间:2017-03-13 16:12:23

标签: c# linq reflection

我有两个使用ff的对象。类:

public class Test {
    public string Name {get; set;}
    public List<Input> Inputs {get;set;}
    ......
    //some other properties I don't need to check
}

public class Input {
    public int VariableA {get;set;}
    public int VariableB {get;set;}
    public List<Sancti> Sancts {get;set;}
}

public class Sancti {
    public string Symbol {get;set;}
    public double Percentage {get;set;}
}

我想检查Test的两个实例是否具有相同的Inputs值。我已经使用循环完成了这个,但我相信这不是这样做的方法。

我已经阅读了一些链接:link1link2但它们对我来说似乎是胡言乱语。是否有更简单的方法可以做到这一点,比如:

test1.Inputs.IsTheSameAs(test2.Inputs)

我真的希望有一种更易读的方法。优先Linq

注意:输入顺序无关紧要。

2 个答案:

答案 0 :(得分:2)

一种方法是检查两个列表之间的设置否定。如果listA否定listB的结果没有元素,则表示listA中的所有内容都存在于listB中。如果反之亦然,则两个列表相等。

bool equal = testA.Inputs.Except(testB.Inputs).Count() == 0 
             && testB.Inputs.Except(testA.Inputs).Count() == 0;

另一个是简单地检查listA的每个元素,看它是否存在于listB中(反之亦然):

bool equal = testA.Inputs.All(x => testB.Inputs.Contains(x)) 
             && testB.Inputs.All(x => testA.Inputs.Contains(x));

这就是说,如果列表中的一个元素与另一个元素中的多个元素“相等”,则这些中的任何一个都会产生误报。例如,使用上述方法将以下两个列表视为相同:

listA = { 1, 2, 3, 4 };
listB = { 1, 1, 2, 2, 3, 3, 4, 4 };

为防止这种情况发生,您需要执行一对一搜索而不是核解决方案。有几种方法可以做到这一点,但一种方法是首先对两个列表进行排序,然后相互检查它们的索引:

var listASorted = testA.Inputs.OrderBy(x => x);
var listBSorted = testB.Inputs.OrderBy(x => x);
bool equal = testA.Inputs.Count == testB.Inputs.Count
             && listASorted.Zip(listBSorted, (x, y) => x == y).All(b => b);  

(如果已经对列表进行了排序,或者您希望确切地检查列表(保留排序),那么您可以跳过此方法的排序步骤。)

然而,使用此方法需要注意的一点是,Input需要实现IComparable才能对它们进行适当的排序。您如何完全实现它取决于您,但一种可能的方法是根据InputVariableA的XOR对VariableB进行排序:

public class Input : IComparable<Input> 
{
    ...

    public int Compare(Input other)
    {
        int a = this.VariableA ^ this.VariableB;
        int b = other.VariableA ^ other.VariableB;
        return a.Compare(b);
    }
}

(此外,Input也应该覆盖GetHashCodeEquals,因为它的答案在其答案中描述了。)

修改

在回到这个答案之后,我现在想提供一个更简单的解决方案:

var listASorted = testA.Inputs.OrderBy(x => x);
var listBSorted = testB.Inputs.OrderBy(x => x);
bool equal = listASorted.SequenceEqual(listBSorted);

(如前所述,如果列表已经排序,或者您希望将它们与现有的排序完整比较,则可以跳过排序步骤。)

SequenceEqual使用特定类型的相等比较器来确定相等性。默认情况下,这意味着检查两个对象之间所有公共属性的值是否相等。如果您想实施不同的方法,可以为IEqualityComparer定义Input

public class InputComparer : IEqualityComparer<Input>
{
    public bool Equals(Input a, Input b)
    {
        return a.variableA == b.variableA
            && a.variableB == b.variableB
            && ... and so on
    }

    public int GetHashCode(Input a)
    {
        return a.GetHashCode();
    }
}

答案 1 :(得分:1)

您可以更改InputSancti类定义,以覆盖EqualsGetHasCode。以下解决方案在以下情况下认为2个输入相等:

  1. VariableA相等且
  2. VariableB相等且
  3. Sancts列表相同,考虑到具有相同Sancti的{​​{1}}元素必须具有相同的Symbol
  4. 如果您的规格不同,您可能需要更改此信息:

    Percentage

    这样做,你只需要检查public class Input { public int VariableA { get; set; } public int VariableB { get; set; } public List<Sancti> Sancts { get; set; } public override bool Equals(object obj) { Input otherInput = obj as Input; if (ReferenceEquals(otherInput, null)) return false; if ((this.VariableA == otherInput.VariableA) && (this.VariableB == otherInput.VariableB) && this.Sancts.OrderBy(x=>x.Symbol).SequenceEqual(otherInput.Sancts.OrderBy(x => x.Symbol))) return true; else { return false; } } public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = 17; // Suitable nullity checks etc, of course :) hash = hash * 23 + VariableA.GetHashCode(); hash = hash * 23 + VariableB.GetHashCode(); hash = hash * 23 + Sancts.GetHashCode(); return hash; } } } public class Sancti { public string Symbol { get; set; } public double Percentage { get; set; } public override bool Equals(object obj) { Sancti otherInput = obj as Sancti; if (ReferenceEquals(otherInput, null)) return false; if ((this.Symbol == otherInput.Symbol) && (this.Percentage == otherInput.Percentage) ) return true; else { return false; } } public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = 17; // Suitable nullity checks etc, of course :) hash = hash * 23 + Symbol.GetHashCode(); hash = hash * 23 + Percentage.GetHashCode(); return hash; } } } 是否相等:

    Input