HashSet 无法正常工作,原因或替代方法?

HashSet does not work correctly, reason or alternatives?

我有一个 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();

错误-Class:

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

覆盖默认的 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

记得处理 File 字符串上的 null 值。 (例如,可以将其替换为 String.Empty。)将哈希码“缓存”到私有变量中也很常见,因此一旦计算出缓存值,就可以在随后调用 GetHashCode() 时返回。为此,您很可能还需要使 class 不可变。

(您不必对 C# 9 的记录类型执行任何操作。)