【发布时间】:2014-06-03 05:22:27
【问题描述】:
我正在按 RegEx 模式对日志记录进行分组。将它们分组后,我想获得每个组的记录的Distinct 计数。对于本例,Distinct 定义为相同的访问键和相同的年、月、日、小时和分钟。
这只是一种更准确地计算不同消费者在堆栈中一直记录的东西的方法。
好的,所以我将它们分组如下:
var knownMessages = logRecords
.Where(record => !string.IsNullOrEmpty(record.InclusionPattern))
.GroupBy(record => new
{
MessagePattern = record.InclusionPattern
})
.Select(g => new KnownMessage
{
MessagePattern = g.Key.MessagePattern,
----> Count = g.Distinct().Count(),
Records = g.ToList()
})
.OrderByDescending(o => o.Count);
而GetHashCode 的类型是这样实现的:
public override int GetHashCode()
{
var visitKeyHash = this.VisitKey == null ?
251 : this.VisitKey.GetHashCode();
var timeHash = this.Time.Year + this.Time.Month + this.Time.Day +
this.Time.Hour + this.Time.Minute;
return ((visitKeyHash * 251) + timeHash) * 251;
}
但是,例如,在列表中,我有三个记录返回相同的哈希码1439926797;我仍然得到3 的计数。我知道它正在利用GetHashCode(正如我所料)进行比较,因为我在那里有一个断点来查看哈希码是什么。
我错过了什么?
【问题讨论】:
-
首先,在一个不会导致冲突的庄园中将哈希值组合在一起并不是一个很好的方法。其次,你没有展示
Equals的定义,这对于相等的定义当然是必不可少的。 -
@Servy,我认为如果哈希码匹配,它们将被视为相等。
-
你应该实现 IEquitable
-
@MichaelPerrenoud 不。重要的是始终覆盖两者或都不覆盖,而不是只覆盖一个,并且无论何时覆盖两者都应该使用相同的“平等”一般定义,否则会发生坏事。跨度>
-
@MichaelPerrenoud 逻辑是:如果
a.GetHashcode() != b.GetHashCode()然后a != b,如果a.GetHashCode() == b.GetHashCode() && a.Equals(b)然后a == b,所有GetHashcode()为你做的是让你跳过Equals()检查你是否有两个不同的值。这就是为什么你需要同时实现这两个,如果你只实现Equals(),那么a.GetHashCode() == b.GetHashCode()步骤会失败,它永远不会尝试你实现的Equals()。