我有一个像这样的人类:
Public Class Person
{
public int Id {get; set;}
public int FirstName {get; set;}
public int LastName {get; set;}
}
我创建了一个Person对象列表:
List<Person> AllPersons = GetAllPersons();
在GetAllPersons()中,我有这段代码,根据Id提供唯一且非重复的人物对象。
return this.colLoadExternalData.GroupBy(p => p, new MyClass()).Where(g => g.Count() == 1).Select(g => g.Single()).ToList();
如果来源有两个Id = 123的人,则表示列表中没有123。
这是实现IEqualityComparer
的类public class MyClass : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
return x.Id == y.Id;
}
public int GetHashCode(Person obj)
{
return obj.Id.GetHashCode();
}
}
MyClass设置基于Id的身份。
我有一个外部配置文件,其中有一个提供设置person类的标识属性的条件,如FirstName或LastName等,它将根据该属性值标识一个唯一的人。
因此,如果配置文件将'FirstName'作为键,那么MyClass将如下所示:
public class MyClass : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
return x.FirstName == y.FirstName;
}
public int GetHashCode(Person obj)
{
return obj.FirstName.GetHashCode();
}
}
我实际上在向其添加人物对象之前使用了字典,但如果源具有重复的条目,例如两个id为123的人,则仍会添加一个人物对象。 如果可以使用字典对象完成此操作,请确保最终集合确实具有唯一对象,并且不包括来自外部源的重复记录,这将是很好的。
我能做的是在单独的列表中维护一份重复列表。 在该列表上执行一个简单的foreach并从字典中删除这些person对象,如下所示:
foreach(var dup in Duplicates)
{
UniquePersonObjects.Remove(dup);
}
这里没有使用IEqualityComparer,只需将外部源中的记录添加到字典中,然后根据重复列表进一步过滤该字典。
有更好的方法吗?
问候。
答案 0 :(得分:1)
我目前找到的最佳实施方法,您可以在following link
找到
public class EqualityComparer:IEqualityComparer
{
private Func equalsFunction;
private Func getHashCodeFunction;
public EqualityComparer(Func<T, T, bool> equalsFunction)
{
this.equalsFunction = equalsFunction;
}
public EqualityComparer(Func<T, T, bool> equalsFunction,
Func<T, int> getHashCodeFunction) : this(equalsFunction)
{
this.getHashCodeFunction = getHashCodeFunction;
}
public bool Equals(T a, T b)
{
return equalsFunction(a, b);
}
public int GetHashCode(T obj)
{
if (getHashCodeFunction == null)
return obj.GetHashCode();
return getHashCodeFunction(obj);
}
public EqualityComparer(Func<T, T, bool> equalsFunction)
{
this.equalsFunction = equalsFunction;
}
public EqualityComparer(Func<T, T, bool> equalsFunction,
Func<T, int> getHashCodeFunction) : this(equalsFunction)
{
this.getHashCodeFunction = getHashCodeFunction;
}
public bool Equals(T a, T b)
{
return equalsFunction(a, b);
}
public int GetHashCode(T obj)
{
if (getHashCodeFunction == null)
return obj.GetHashCode();
return getHashCodeFunction(obj);
}
现在您可以编写自己的过滤方法,例如:
}
答案 1 :(得分:0)
您可以使用MyClass
中的配置来处理不同的检查:
public class MyClass : IEqualityComparer<Person>
{
// here you set the configuration
private PersonCompareConfiguration personCompareConfiguration;
public bool Equals(Person x, Person y)
{
switch(personCompareConfiguration)
{
case CompareId:
return x.Id == y.Id;
break;
case CompareFirstname:
return x.FirstName == y.FirstName;
break;
}
throw new InvalidArgumentException("personCompareConfiguration cannot be handled");
}
public int GetHashCode(Person obj)
{
switch(personCompareConfiguration)
{
case CompareId:
return obj.Id.GetHashCode();
break;
case CompareFirstname:
return obj.FirstName.GetHashCode();
break;
}
throw new InvalidArgumentException("personCompareConfiguration cannot be handled");
}
}
public enum PersonCompareConfiguration
{
CompareId,
CompareFirstname
}
另一种(更聪明的)方法是使用MEF导出IEqualityComparer<Person>
的实现。请查看this answer,其中介绍了如何导出和导入通用接口。