Удалить элементы списка из списка с помощью Removeall Lambda Hashset

Я использую FileHelpers для разбора 2-х текстовых файлов, которые содержат информацию о пользователях активного каталога. Класс Users определяется как:

    [DelimitedRecord(",")]

public class Users
{
    public string LogonName;

    public string DisplayName;

    public string FirstName;

    public string LastName;

    public string SamAccountName;

    public string Password;

    public string Identity;

}

Файлы CSV содержат LogonName,DisplayName,FirstName,LastName,SamAccountName, Пароль, Идентификатор MM0123,Mothhair Mayeye,Mathhair,Mayeye,MM0123,secrtpwd,Group1

Большинство пользователей в обоих файлах идентичны. Есть около 6500 записей.

Я ожидаю, что после этого работает:

        List<Users> UserListCur = new List<Users>();
        List<Users> UserListLR = new List<Users>();
        FileHelperEngine engine = new FileHelperEngine(typeof(Users));

        var records = engine.ReadFile(@"C:\\users.csv");
        var lrrecords = engine.ReadFile(@"C:\\lastrun.csv");

        foreach (Users record in records)
        {

            UserListCur.Add(record);
        }

        foreach (Users record in lrrecords)
        {

            UserListLR.Add(record);
        }


        UserListCur.RemoveAt(0);
        UserListLR.RemoveAt(0);


        var UserListLRhash = new HashSet<Users>(UserListLR);
        UserListCur.RemoveAll(x => UserListLRhash.Contains(x));

Записи из UserListLR должны быть удалены из UserListCur, но UserListCur не изменяется. Большинство пользовательских записей идентичны, поэтому я не уверен, почему он не удаляет ни одну из них.

1 ответ

Решение

Вы должны либо переопределить Equals(object) а также GetHashCode() в пользователях, чтобы определить, что делает двух пользователей равными, или вы должны написать класс, который реализует IEqualityComparer<Users> и передайте этот класс конструктору созданного вами HashSet.

Когда вы просто используете реализацию равенства по умолчанию, как это делает ваш код, единственным способом, которым два пользователя будут считаться равными, является Object.RefrenceEquals(user1, user2) возвращает истину.

Вот пример создания компаратора и его передачи.

public sealed class UsersEqualityComparer : IEqualityComparer<Users>
{
    public bool Equals(Users x, Users y)
    {
        if (ReferenceEquals(x, y)) return true;
        if (ReferenceEquals(x, null)) return false;
        if (ReferenceEquals(y, null)) return false;
        if (x.GetType() != y.GetType()) return false;
        return string.Equals(x.LogonName, y.LogonName) && string.Equals(x.DisplayName, y.DisplayName) &&
               string.Equals(x.FirstName, y.FirstName) && string.Equals(x.LastName, y.LastName) &&
               string.Equals(x.SamAccountName, y.SamAccountName) && string.Equals(x.Password, y.Password) &&
               string.Equals(x.Identity, y.Identity);
    }

    public int GetHashCode(Users obj)
    {
        if(ReferenceEquals(obj, null))
            throw new ArgumentNullException("obj");

        unchecked
        {
            var hashCode = (obj.LogonName != null ? obj.LogonName.GetHashCode() : 0);
            hashCode = (hashCode * 397) ^ (obj.DisplayName != null ? obj.DisplayName.GetHashCode() : 0);
            hashCode = (hashCode * 397) ^ (obj.FirstName != null ? obj.FirstName.GetHashCode() : 0);
            hashCode = (hashCode * 397) ^ (obj.LastName != null ? obj.LastName.GetHashCode() : 0);
            hashCode = (hashCode * 397) ^ (obj.SamAccountName != null ? obj.SamAccountName.GetHashCode() : 0);
            hashCode = (hashCode * 397) ^ (obj.Password != null ? obj.Password.GetHashCode() : 0);
            hashCode = (hashCode * 397) ^ (obj.Identity != null ? obj.Identity.GetHashCode() : 0);
            return hashCode;
        }
    }
}

и ваш код меняется на

    List<Users> UserListCur = new List<Users>();
    List<Users> UserListLR = new List<Users>();
    FileHelperEngine engine = new FileHelperEngine(typeof(Users));

    var records = engine.ReadFile(@"C:\\users.csv");
    var lrrecords = engine.ReadFile(@"C:\\lastrun.csv");

    foreach (Users record in records)
    {

        UserListCur.Add(record);
    }

    foreach (Users record in lrrecords)
    {

        UserListLR.Add(record);
    }


    UserListCur.RemoveAt(0);
    UserListLR.RemoveAt(0);


    var UserListLRhash = new HashSet<Users>(UserListLR, new UsersEqualityComparer());
    UserListCur.RemoveAll(x => UserListLRhash.Contains(x));
Другие вопросы по тегам