c# - 自定义 IEqualityComparer 使用 LINQ 计算两个列表之间的差异,除了
问题描述
我正在使用这个答案两个列表之间的差异来查找使用 Linq 的两个列表之间的差异Except
。但是,列表中的对象是泛型类型,所以我为泛型类型编写了一个比较器,然后将它传递给 except 方法。但是我收到以下错误消息:
错误 CS1929 'List' 不包含 'Except' 的定义,并且最佳扩展方法重载'ParallelEnumerable.Except(ParallelQuery, ParallelQuery, IEqualityComparer)'需要'ParallelQuery'类型的接收器
我的电话:
var differenceList = list1.Except(list2, new PropertyComparer<Guid>("ObjectId"));
我的比较器:
public class PropertyComparer<T> : IEqualityComparer<T>
{
private PropertyInfo _PropertyInfo;
public PropertyComparer(string propertyName)
{
_PropertyInfo = typeof(T).GetProperty(propertyName,
BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public);
if (_PropertyInfo == null)
{
throw new ArgumentException(
string.Format("{0} is not a property of type {1}.", propertyName, typeof(T)));
}
}
public int GetHashCode(T obj)
{
object propertyValue = _PropertyInfo.GetValue(obj, null);
if (obj == null) return 0;
return propertyValue.GetHashCode();
}
public bool Equals(T x, T y)
{
object xValue = _PropertyInfo.GetValue(x, null);
object yValue = _PropertyInfo.GetValue(y, null);
if (xValue == null)
{
return yValue == null;
}
return xValue.Equals(yValue);
}
}
System.Linq
并且从符合我的比较器的 except 方法的声明中:
public static IEnumerable<TSource> Except<TSource>(
this IEnumerable<TSource> first,
IEnumerable<TSource> second,
IEqualityComparer<TSource> comparer
);
我做错了什么,我怎样才能让它工作?
更新
list1
和list2
类型:
List<Contact>
Contact
在哪里
public class Contact : EntityBase
{
public Guid ContactId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Email> Emails {get; set;}
}
EntityBase
是
public class EntityBase : IEntity
{
public IQueryable<T> GetDBEntities<T>(ApplicationDbContext db) where T : class
{
return db.Set<T>();
}
public List<T> GetLocalEntities<T>() where T : class
{
var localProperties = this.GetType().GetProperties();
foreach (var localProperty in localProperties)
{
var localPropertyValue = localProperty.GetValue(this);
if (localPropertyValue != null && localPropertyValue.IsGenericList() == true)
{
var localPropertyValueType = localPropertyValue.GetType(); // List<object>
var localPropertyValueTypeDecoupled = localPropertyValueType.GetGenericArguments().Single(); // List<T>
if (localPropertyValueTypeDecoupled == typeof(T))
{
return (List<T>)localPropertyValue;
}
}
}
throw new Exception("Entity Types Validation Error");
}
public void ProcessEntityReference<T>(ApplicationDbContext db) where T : class
{
// T is Email
var remoteList = this.GetDBEntities<T>(db).ToList();
var updatedList = GetLocalEntities<T>();
var toBeAdded = updatedList.Except(remoteList, new PropertyComparer<Guid>("ContactId"));
var toBeDeleted = new List<object>();
throw new NotImplementedException();
}
public void ProcessEntityReferences(ApplicationDbContext db)
{
this.ProcessEntityReference<Email>(db);
}
}
解决方案
您应该将列表使用的相同类型传递给 except 方法,在您的示例中,您正在使用Guid
但它应该是 type Contact
,此外,您的Contact
类没有名为“ObjectId”的属性,请尝试将其更改为“ ContactId
” ,以下似乎工作正常:
static void Main(string[] args)
{
var list1 = new List<Contact>();
list1.Add(new Contact() { ContactId = Guid.Parse("FB58F102-0CE4-4914-ABFF-ABBD3895D719") });
list1.Add(new Contact() { ContactId = Guid.Parse("5A201238-6036-4385-B848-DEE598A3520C") });
var list2 = new List<Contact>();
list2.Add(new Contact() { ContactId = Guid.Parse("FB58F102-0CE4-4914-ABFF-ABBD3895D719") });
var list3 = list1.Except(list2, new PropertyComparer<Contact>("ContactId"));
foreach (var item in list3)
Console.WriteLine(item.ContactId.ToString());
Console.ReadLine();
}
public class Contact
{
public Guid ContactId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class PropertyComparer<T> : IEqualityComparer<T>
{
private PropertyInfo _PropertyInfo;
public PropertyComparer(string propertyName)
{
_PropertyInfo = typeof(T).GetProperty(propertyName,
BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public);
if (_PropertyInfo == null)
{
throw new ArgumentException(
string.Format("{0} is not a property of type {1}.", propertyName, typeof(T)));
}
}
public int GetHashCode(T obj)
{
object propertyValue = _PropertyInfo.GetValue(obj, null);
if (obj == null) return 0;
return propertyValue.GetHashCode();
}
public bool Equals(T x, T y)
{
object xValue = _PropertyInfo.GetValue(x, null);
object yValue = _PropertyInfo.GetValue(y, null);
if (xValue == null)
{
return yValue == null;
}
return xValue.Equals(yValue);
}
}
输出:
5a201238-6036-4385-b848-dee598a3520c
推荐阅读
- python - 无法将特殊字符插入列表
- javascript - 如何将递归函数的每次迭代返回到另一个函数
- rest - 为什么要在没有第三方的情况下使用 OAuth?
- python - 如何根据条件对熊猫数据框中的值进行分组
- testcomplete - 如何在 TestComplete 中自动化 ODBC 数据源管理器窗口
- python - 使用Faker返回一个范围之间的假年份?
- android - 从图库中选择视频时,Android 10 像素 2 中出现无效列纬度错误
- database - 在不删除数据库的情况下重新安装 MongoDB
- sql-server - 在 MsSql-Statement 中填写固定小时类别
- junit - Junit 测试用例中 NonStrictExpections 到期望转换的问题