HashSet не работает правильно, причина или альтернативы? - PullRequest
0 голосов
/ 05 августа 2020

У меня есть HashSet с ошибками, <Error>ErrorList. «Ошибка» имеет свойства «файл» и «блок». Поэтому я заполняю свой HashSet рядом ошибок, некоторые из которых точно такие же и поэтому повторяются. HashSet полностью допускает множественные вхождения. В качестве последней попытки я создал отдельный список и выделил его: List<Error> noDupes = ErrorList.Distinct().ToList(); Но и здесь мой список не изменился. Почему не работают ни хэшсет, ни мой список noDupes? Есть ли альтернативные решения?

Вот важная часть моего кода:

        #region Properties
        HashSet<Error> ErrorList { get; set; } = new HashSet<Error>();
        private Stopwatch StopWatch { get; set; } = new Stopwatch();
        private string CSVFile { get; set; } = null;
        int n;
        #endregion
                    ErrorList.Add(new Error
                    {
                        File = x,
                        Block = block
                    }); ;
                    
                    

                    n = FileCall.IndexOf(i);
                    int p = n * 100 / FileCall.Count;
                    SetConsoleProgress(n.ToString("N0"), p);
                }
            } 

            int nx = 0;
            List<Error> noDupes = ErrorList.Distinct().ToList();

Класс ошибки:

namespace ApplicationNamespace
{
    public class Error
    {
        public string File { set; get; }
        public int Block { set; get; }
    }
}

1 Ответ

0 голосов
/ 05 августа 2020

Переопределите реализации по умолчанию Equals() и GetHashCode() (например, другие, упомянутые в комментариях), чтобы HashSet<> или Distinct() работали. Вы также можете реализовать IEquatable<>, что потребует от вас переопределения методов Equals() и GetHashCode().

public class Error : IEquatable<Error>
{

    public string File { set; get; }
    public int Block { set; get; }


    public bool Equals(Error other)
    {

        // Check whether the compared object is null.
        if (Object.ReferenceEquals(other, null)) return false;

        // Check whether the compared object references the same data.
        if (Object.ReferenceEquals(this, other)) return true;

        // Check whether the error's properties are equal.
        return File == other.File && Block == other.Block;
    }

    // If Equals() returns true for a pair of objects
    // then GetHashCode() must return the same value for these objects.
    public override int GetHashCode()
    {
        return $"{Block}-{File}".GetHashCode(); // adjust this as you see fit
    }
}

Ссылка: https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.distinct?view=netcore-3.1

Не забудьте обработать значения null в строке File. (Можно заменить его, например, на String.Empty.) Также обычно "кэшируют" хэш-код в частной переменной, так что после вычисления кэшированное значение может быть возвращено при последующих вызовах GetHashCode(). Для этого вам, скорее всего, также потребуется сделать класс неизменяемым.

(Вам не придется делать ничего из этого с типами записей C# 9.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...