0

我有一个像这样的人类:

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 的身份。

我有一个外部配置文件,其中有一个规定来设置人员类的身份属性,如 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 并从字典中删除这些人员对象,如下所示:

foreach(var dup in Duplicates)
{
  UniquePersonObjects.Remove(dup);
}

这里没有使用 IEqualityComparer,只需将来自外部源的记录添加到字典中,然后根据重复列表进一步过滤该字典。

有一个更好的方法吗?

问候。

4

2 回答 2

1

到目前为止我设法找到的最佳实现,您可以在以下链接中找到

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);
}

}

现在您可以编写自己的过滤方法,例如:

EqualityComparer equalityComparer = new EqualityComparer((s1, s2) => s1.Id == s2.Id);

于 2014-04-15T07:37:52.017 回答
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>. 看看这个答案,它描述了如何导出和导入通用接口。

于 2013-03-04T09:29:49.600 回答