【问题标题】:HashSet does not work correctly, reason or alternatives?HashSet 不能正常工作,原因还是替代方案?
【发布时间】:2020-08-05 09:03:13
【问题描述】:

我有一个带有错误的 HashSet,<Error>ErrorList。 “错误”具有属性“文件”和“块”。 所以我用一些错误填充我的 HashSet,其中一些是完全相同的,因此会重复。 HashSet 完全可以容忍多次出现。作为最后一次尝试,我创建了一个单独的列表并加以区分:List<Error> noDupes = ErrorList.Distinct().ToList(); 但在这里我的名单也保持不变。为什么 hashset 和我的 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; }
    }
}

【问题讨论】:

  • 可能是因为您的课程没有实现哈希码?如果您不提供该哈希码的任何信息,基于 hash 的集合应如何自动计算有意义的哈希?
  • 请贴出Error的定义。 HashSet 类不能自动知道您认为“相等”或“重复”的内容。显示您的定义。
  • 请考虑,仅仅因为两个对象在某些属性上共享相同的值并不会使这些对象相等。否则两个名叫约翰的人将是同一个人,他们很确定不是。您必须向您的程序提供平等对您意味着什么。
  • 添加EqualsGetHashCode方法的覆盖,或者实现IEquatable&lt;Error&gt;接口

标签: c# list hashset


【解决方案1】:

覆盖默认的 Equals()GetHashCode() 实现(就像 cmets 中提到的其他实现一样)以使 HashSet&lt;&gt;Distinct() 工作。您还可以实现IEquatable&lt;&gt;,这将要求您覆盖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() 时返回。为此,您很可能还需要使该类不可变。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-10
    • 1970-01-01
    • 2013-07-19
    • 2011-09-02
    • 2023-01-09
    • 2013-01-02
    • 2011-10-02
    相关资源
    最近更新 更多