比较两个返回不同结果的列表<object>
Compare two Lists<object> returning different results
我有一个名为 TestResult 的 class,它看起来像这样:
public class TestResult : IEquatable<TestResult> {
public TestResult(string labelName, List<object> correctValues) {
this.LabelName = labelName;
this.SelectedValues = correctValues;
}
public TestResult() {
}
public string LabelName { get; set; }
public List<object> SelectedValues { get; set; }
public override bool Equals(object obj) {
if (ReferenceEquals(null, obj)) {
return false;
}
if (ReferenceEquals(this, obj)) {
return true;
}
return obj.GetType() == GetType() && Equals((TestResult)obj);
}
public override int GetHashCode() {
unchecked {
int hashCode = this.LabelName.GetHashCode();
hashCode = (hashCode * 397) ^ this.SelectedValues.GetHashCode();
return hashCode;
}
}
public bool Equals(TestResult other) {
if (ReferenceEquals(null, other)) {
return false;
}
if (ReferenceEquals(this, other)) {
return true;
}
bool areEqual = false;
if (this.LabelName == other.LabelName) {
areEqual = true;
}
if (this.SelectedValues?.Count != other.SelectedValues?.Count) {
return false;
}
areEqual = this.SelectedValues.OrderBy(x => x).SequenceEqual(other.SelectedValues.OrderBy(x => x));
return areEqual;
}
/// <summary>
/// Override ==(you must ovverride this so if a developer called == it will return the same result as if they called Equals
/// </summary>
/// <param name="obj1"></param>
/// <param name="obj2"></param>
/// <returns></returns>
public static bool operator ==(TestResult obj1, TestResult obj2) {
if (ReferenceEquals(obj1, obj2)) {
return true;
}
if (ReferenceEquals(obj1, null)) {
return false;
}
if (ReferenceEquals(obj2, null)) {
return false;
}
bool areEqual = false;
if (obj1.LabelName == obj2.LabelName) {
areEqual = true;
}
if (obj1.SelectedValues?.Count != obj2.SelectedValues?.Count) {
return false;
}
areEqual = obj1.SelectedValues.OrderBy(x => x).SequenceEqual(obj2.SelectedValues.OrderBy(x => x));
return areEqual;
}
/// <summary>
/// No need to repeat myself, just return the opposite of the == function
/// </summary>
/// <param name="obj1"></param>
/// <param name="obj2"></param>
/// <returns></returns>
public static bool operator !=(TestResult obj1, TestResult obj2) {
return !(obj1 == obj2);
}
如您所见,我已经覆盖了 equals 方法,因此我可以在创建列表时比较我的对象。
然后我有一个单元测试来测试我的 equals 方法,它看起来像这样:
[TestMethod]
public void ReturnIncorrectTestResults_IncorrectValuesSubmitted_3LabelsWillBeReturned() {
List<string> failedLabelNames;
var submittedResults = new List<Repository.TestManagement.Models.TestResult> {
new Repository.TestManagement.Models.TestResult("Question1Label", new List<object> { true }),
new Repository.TestManagement.Models.TestResult("Question2Label", new List<object> { true }), //Difference
new Repository.TestManagement.Models.TestResult("Question3Label", new List<object> { 3, 4 }),
new Repository.TestManagement.Models.TestResult("Question4Label", new List<object> { true }),
new Repository.TestManagement.Models.TestResult("Question5Label", new List<object> { 1, 3 }), //Difference
new Repository.TestManagement.Models.TestResult("Question6Label", new List<object> { 1, 2, 3, 4 }),
new Repository.TestManagement.Models.TestResult("Question7Label", new List<object> { 1, 2, 3 }),
new Repository.TestManagement.Models.TestResult("Question8Label", new List<object> { 2 }),
new Repository.TestManagement.Models.TestResult("Question9Label", new List<object> { 3 }), //Difference
new Repository.TestManagement.Models.TestResult("Question10Label", new List<object> { 1, 2, 3, 4, 5 })
};
var validResults = new List<Repository.TestManagement.Models.TestResult> {
new Repository.TestManagement.Models.TestResult("Question1Label", new List<object> { false }),
new Repository.TestManagement.Models.TestResult("Question2Label", new List<object> { true }),
new Repository.TestManagement.Models.TestResult("Question3Label", new List<object> { 3, 4 }),
new Repository.TestManagement.Models.TestResult("Question4Label", new List<object> { true }),
new Repository.TestManagement.Models.TestResult("Question5Label", new List<object> { 5,6 }),
new Repository.TestManagement.Models.TestResult("Question6Label", new List<object> { 1, 2, 3, 4 }),
new Repository.TestManagement.Models.TestResult("Question7Label", new List<object> { 1, 2, 3 }),
new Repository.TestManagement.Models.TestResult("Question8Label", new List<object> { 2 }),
new Repository.TestManagement.Models.TestResult("Question9Label", new List<object> { 1 }),
new Repository.TestManagement.Models.TestResult("Question10Label", new List<object> { 1, 2, 3, 4, 5 })
};
failedLabelNames = _iTestManager.ReturnIncorrectTestLabels(submittedResults, validResults);
Assert.IsTrue(failedLabelNames.Count == 3);
}
所以我的应用程序代码中也有一个方法调用相同的 equals 函数:
public List<string> ReturnIncorrectTestLabels(List<TestResult> submittedResults, List<TestResult> acceptedResults) {
if (submittedResults.Count != acceptedResults.Count)
throw new ArgumentException($"The submitted results count is {submittedResults.Count} and the accepted results count is {acceptedResults.Count}. Amount of results must be equal.");
/*Compare the valid results against the submitted results. We join on the label names and
compare the results. Please not that this works because I have overridden the equals in
the TestResult class*/
var failedResultLabelNames = (from accepted in acceptedResults
join submitted in submittedResults
on accepted.LabelName equals submitted.LabelName
where accepted != submitted
select accepted?.LabelName).ToList();
return failedResultLabelNames;
}
我用它来比较两个结果列表和return任何失败的值。
奇怪的是我的单元测试通过了,但是当我在我的网站上测试时它 return 是错误的并且对象不相等。
例如,如果我提交两个如下所示的列表:
var list1 = new List<TestResult> {
new TestResult("Question1Label", new List<object> { 1,2,3 }),
new TestResult("Question2Label", new List<object> { 4,5,6 })
};
var list2 = new List<TestResult> {
new TestResult("Question1Label", new List<object> { "1","2","3" }),
new TestResult("Question2Label", new List<object> { "4","5","6" })
};
然后我为我的两个列表调用了 ReturnIncorrectTestLabels 方法,它 return 两个列表项都是 "failed"。
为什么会这样?
这是因为 !=
的执行方式类似于交叉连接,因此所有内容都会与所有内容进行比较,因此当第一项与第二项进行比较时,您会得到 failedResult,当第二项与第一项进行比较时 - 您也会得到 failedResult .
这是因为您加入的 LabelName
对于 list1
和 list2
中的两个项目是相同的。尝试比较你的标签名称何时是唯一的(因为它们在你的单元测试中)并且它应该给出期望和预期的结果。
var list1 = new List<TestResult> {
new TestResult("1", new List<object> { 1,2,3 }),
new TestResult("2", new List<object> { 4,5,6 })
};
var list2 = new List<TestResult> {
new TestResult("1", new List<object> { 1,2,3 }),
new TestResult("2", new List<object> { 4,5,6 })
};
var test = ReturnIncorrectTestLabels(list1, list2);
public static bool operator ==(TestResult obj1, TestResult obj2) {
if (ReferenceEquals(obj1, obj2)) {
return true;
}
if (ReferenceEquals(obj1, null)) {
return false;
}
if (ReferenceEquals(obj2, null)) {
return false;
}
bool areEqual = false;
if (obj1.LabelName == obj2.LabelName) {
areEqual = true;
}
if (obj1.SelectedValues?.Count != obj2.SelectedValues?.Count) {
return false;
}
//Order to make sure that they are in correct order to be compared
obj1.SelectedValues = obj1.SelectedValues.OrderBy(x => x).ToList();
obj2.SelectedValues = obj2.SelectedValues.OrderBy(x => x).ToList();
for (int i = 0; i < obj1.SelectedValues.Count; i++) {
var type = obj1.SelectedValues[i].GetType();
//Use a dynamic so I can cast to the correct types at run time and compare
dynamic castedObj1Val = Convert.ChangeType(obj1.SelectedValues[i], type);
dynamic castedObj2Val = Convert.ChangeType(obj2.SelectedValues[i], type);
if (castedObj1Val != castedObj2Val)
return false;
}
return areEqual;
}
我正在比较两种不同的类型,所以在比较之前我必须将它们转换为正确的类型
我有一个名为 TestResult 的 class,它看起来像这样:
public class TestResult : IEquatable<TestResult> {
public TestResult(string labelName, List<object> correctValues) {
this.LabelName = labelName;
this.SelectedValues = correctValues;
}
public TestResult() {
}
public string LabelName { get; set; }
public List<object> SelectedValues { get; set; }
public override bool Equals(object obj) {
if (ReferenceEquals(null, obj)) {
return false;
}
if (ReferenceEquals(this, obj)) {
return true;
}
return obj.GetType() == GetType() && Equals((TestResult)obj);
}
public override int GetHashCode() {
unchecked {
int hashCode = this.LabelName.GetHashCode();
hashCode = (hashCode * 397) ^ this.SelectedValues.GetHashCode();
return hashCode;
}
}
public bool Equals(TestResult other) {
if (ReferenceEquals(null, other)) {
return false;
}
if (ReferenceEquals(this, other)) {
return true;
}
bool areEqual = false;
if (this.LabelName == other.LabelName) {
areEqual = true;
}
if (this.SelectedValues?.Count != other.SelectedValues?.Count) {
return false;
}
areEqual = this.SelectedValues.OrderBy(x => x).SequenceEqual(other.SelectedValues.OrderBy(x => x));
return areEqual;
}
/// <summary>
/// Override ==(you must ovverride this so if a developer called == it will return the same result as if they called Equals
/// </summary>
/// <param name="obj1"></param>
/// <param name="obj2"></param>
/// <returns></returns>
public static bool operator ==(TestResult obj1, TestResult obj2) {
if (ReferenceEquals(obj1, obj2)) {
return true;
}
if (ReferenceEquals(obj1, null)) {
return false;
}
if (ReferenceEquals(obj2, null)) {
return false;
}
bool areEqual = false;
if (obj1.LabelName == obj2.LabelName) {
areEqual = true;
}
if (obj1.SelectedValues?.Count != obj2.SelectedValues?.Count) {
return false;
}
areEqual = obj1.SelectedValues.OrderBy(x => x).SequenceEqual(obj2.SelectedValues.OrderBy(x => x));
return areEqual;
}
/// <summary>
/// No need to repeat myself, just return the opposite of the == function
/// </summary>
/// <param name="obj1"></param>
/// <param name="obj2"></param>
/// <returns></returns>
public static bool operator !=(TestResult obj1, TestResult obj2) {
return !(obj1 == obj2);
}
如您所见,我已经覆盖了 equals 方法,因此我可以在创建列表时比较我的对象。
然后我有一个单元测试来测试我的 equals 方法,它看起来像这样:
[TestMethod]
public void ReturnIncorrectTestResults_IncorrectValuesSubmitted_3LabelsWillBeReturned() {
List<string> failedLabelNames;
var submittedResults = new List<Repository.TestManagement.Models.TestResult> {
new Repository.TestManagement.Models.TestResult("Question1Label", new List<object> { true }),
new Repository.TestManagement.Models.TestResult("Question2Label", new List<object> { true }), //Difference
new Repository.TestManagement.Models.TestResult("Question3Label", new List<object> { 3, 4 }),
new Repository.TestManagement.Models.TestResult("Question4Label", new List<object> { true }),
new Repository.TestManagement.Models.TestResult("Question5Label", new List<object> { 1, 3 }), //Difference
new Repository.TestManagement.Models.TestResult("Question6Label", new List<object> { 1, 2, 3, 4 }),
new Repository.TestManagement.Models.TestResult("Question7Label", new List<object> { 1, 2, 3 }),
new Repository.TestManagement.Models.TestResult("Question8Label", new List<object> { 2 }),
new Repository.TestManagement.Models.TestResult("Question9Label", new List<object> { 3 }), //Difference
new Repository.TestManagement.Models.TestResult("Question10Label", new List<object> { 1, 2, 3, 4, 5 })
};
var validResults = new List<Repository.TestManagement.Models.TestResult> {
new Repository.TestManagement.Models.TestResult("Question1Label", new List<object> { false }),
new Repository.TestManagement.Models.TestResult("Question2Label", new List<object> { true }),
new Repository.TestManagement.Models.TestResult("Question3Label", new List<object> { 3, 4 }),
new Repository.TestManagement.Models.TestResult("Question4Label", new List<object> { true }),
new Repository.TestManagement.Models.TestResult("Question5Label", new List<object> { 5,6 }),
new Repository.TestManagement.Models.TestResult("Question6Label", new List<object> { 1, 2, 3, 4 }),
new Repository.TestManagement.Models.TestResult("Question7Label", new List<object> { 1, 2, 3 }),
new Repository.TestManagement.Models.TestResult("Question8Label", new List<object> { 2 }),
new Repository.TestManagement.Models.TestResult("Question9Label", new List<object> { 1 }),
new Repository.TestManagement.Models.TestResult("Question10Label", new List<object> { 1, 2, 3, 4, 5 })
};
failedLabelNames = _iTestManager.ReturnIncorrectTestLabels(submittedResults, validResults);
Assert.IsTrue(failedLabelNames.Count == 3);
}
所以我的应用程序代码中也有一个方法调用相同的 equals 函数:
public List<string> ReturnIncorrectTestLabels(List<TestResult> submittedResults, List<TestResult> acceptedResults) {
if (submittedResults.Count != acceptedResults.Count)
throw new ArgumentException($"The submitted results count is {submittedResults.Count} and the accepted results count is {acceptedResults.Count}. Amount of results must be equal.");
/*Compare the valid results against the submitted results. We join on the label names and
compare the results. Please not that this works because I have overridden the equals in
the TestResult class*/
var failedResultLabelNames = (from accepted in acceptedResults
join submitted in submittedResults
on accepted.LabelName equals submitted.LabelName
where accepted != submitted
select accepted?.LabelName).ToList();
return failedResultLabelNames;
}
我用它来比较两个结果列表和return任何失败的值。
奇怪的是我的单元测试通过了,但是当我在我的网站上测试时它 return 是错误的并且对象不相等。
例如,如果我提交两个如下所示的列表:
var list1 = new List<TestResult> {
new TestResult("Question1Label", new List<object> { 1,2,3 }),
new TestResult("Question2Label", new List<object> { 4,5,6 })
};
var list2 = new List<TestResult> {
new TestResult("Question1Label", new List<object> { "1","2","3" }),
new TestResult("Question2Label", new List<object> { "4","5","6" })
};
然后我为我的两个列表调用了 ReturnIncorrectTestLabels 方法,它 return 两个列表项都是 "failed"。
为什么会这样?
这是因为 !=
的执行方式类似于交叉连接,因此所有内容都会与所有内容进行比较,因此当第一项与第二项进行比较时,您会得到 failedResult,当第二项与第一项进行比较时 - 您也会得到 failedResult .
这是因为您加入的 LabelName
对于 list1
和 list2
中的两个项目是相同的。尝试比较你的标签名称何时是唯一的(因为它们在你的单元测试中)并且它应该给出期望和预期的结果。
var list1 = new List<TestResult> {
new TestResult("1", new List<object> { 1,2,3 }),
new TestResult("2", new List<object> { 4,5,6 })
};
var list2 = new List<TestResult> {
new TestResult("1", new List<object> { 1,2,3 }),
new TestResult("2", new List<object> { 4,5,6 })
};
var test = ReturnIncorrectTestLabels(list1, list2);
public static bool operator ==(TestResult obj1, TestResult obj2) {
if (ReferenceEquals(obj1, obj2)) {
return true;
}
if (ReferenceEquals(obj1, null)) {
return false;
}
if (ReferenceEquals(obj2, null)) {
return false;
}
bool areEqual = false;
if (obj1.LabelName == obj2.LabelName) {
areEqual = true;
}
if (obj1.SelectedValues?.Count != obj2.SelectedValues?.Count) {
return false;
}
//Order to make sure that they are in correct order to be compared
obj1.SelectedValues = obj1.SelectedValues.OrderBy(x => x).ToList();
obj2.SelectedValues = obj2.SelectedValues.OrderBy(x => x).ToList();
for (int i = 0; i < obj1.SelectedValues.Count; i++) {
var type = obj1.SelectedValues[i].GetType();
//Use a dynamic so I can cast to the correct types at run time and compare
dynamic castedObj1Val = Convert.ChangeType(obj1.SelectedValues[i], type);
dynamic castedObj2Val = Convert.ChangeType(obj2.SelectedValues[i], type);
if (castedObj1Val != castedObj2Val)
return false;
}
return areEqual;
}
我正在比较两种不同的类型,所以在比较之前我必须将它们转换为正确的类型