我有两个完全相同类型对象的列表。一个人的物品多于另一个。我想找到两者之间的区别,并尝试了多种方式,但似乎都返回完整列表,而不是差异是一个项目或更多。
List<Permission> defaultPermList = defaultRole.Permissions.ToList();
foreach (var role in roles)
{
List<Permission> rolePermList = role.Permissions.ToList();
//All 3 below return the full set of defaultPermList. not the difference of the two lists
var permissions1 = defaultPermList.RemoveAll(x => rolePermList.Contains(x));
var permissions2 = defaultPermList.Where(x => !rolePermList.Contains(x)).ToList();
var permissions3 = defaultPermList.Except(rolePermList).ToList();
}
我已经查看了许多其他问题和答案,因此我尝试了不同的尝试。
答案 0 :(得分:3)
Linq .Except 应该能够比较Permissions对象的相等性。如果您可以访问权限源代码,则只需覆盖Equals和GetHashCode。当 defaultPermList.Except(rolePermList).ToList()将被调用时 - 它首先通过 object.GetHashCode()和具有相同hashCode wolud的thouse比较相等的所有元素与 object.Equals()进行比较,除非我们覆盖它们。
public class Permissions
{
public string Name; // fields just for showing how to use them
public int Rights;
public override bool Equals(object obj)
{
var permission = obj as Permissions;
if (permission != null)
{
if(permission?.Name.Equals(this.Name) && permission.Rights.Equals(this.Rights)
{
return true;
}
}
return false
}
public override int GetHashCode()
{
return Name.GetHashCode() + 3*Rights.GetHashCode(); // you might use any alghorithm you see fit
}
}
这应该足以使除了工作。但如果没有权限访问权限源代码 - 那么你可能应该编写自己的方法并在那里比较项目。
答案 1 :(得分:2)
如果您不喜欢linq方法,您可以自己轻松完成此操作。 基本上,您为所有类型创建一个扩展方法,并遍历每个属性并列出更改(通过反射)。
见这里:
Compare two objects and find the differences
这是没有空指针异常的更好版本:
static class extentions
{
public static List<Variance> DetailedCompare<T>(this T val1, T val2)
{
List<Variance> variances = new List<Variance>();
FieldInfo[] fi = val1.GetType().GetFields();
foreach (FieldInfo f in fi)
{
Variance v = new Variance();
v.Prop = f.Name;
v.valA = f.GetValue(val1);
v.valB = f.GetValue(val2);
if (!Equals(v.valA, v.valB)) variances.Add(v);
}
return variances;
}
}
方差只是一个简单的类:
class Variance
{
public string Prop { get; set; }
public object valA { get; set; }
public object valB { get; set; }
}
用法:
List<Variance> rt = nstanceA.DetailedCompare(InstanceB);