C# – 如何重写 List<T> 的 GetHashCode 以计算 ETag(其中 T 为记录)

M. *_*och 1 c# etag list gethashcode asp.net-core-webapi

对于 NetCore Web APIGET方法,我需要计算返回的 ETag List<T>。T 是 a 形式的 DTO record,仅保存原始类型。

我想计算列表的哈希值。我正在寻找有关如何GetHashCode()实施的信息,但找不到任何信息。object.GetHashCode()的文档 没有说明有关列表或集合的任何信息。通过代码的结果,我观察到每次运行时相同的列表数据都会创建不同的哈希码。我得出的结论是,GetHashCode()将指针值用于引用类型项。

GetHashCode()ofrecord计算每个成员值的哈希码。因此,我通过循环列表项创建了列表哈希代码:

List<GetGroupsDTO> dtoList = commandResult.Value;
int hash = 17;
foreach(GetGroupsDTO dto in dtoList)
{
   hash = hash * 23 + dto.GetHashCode();
}
string eTagPayload = hash.ToString().SurroundWithDoubleQuotes();
Run Code Online (Sandbox Code Playgroud)

List<T>当然,我不想对每个人都这样做。我想覆盖GetHashCode(),但我正在努力解决。我不知道如何覆盖通用列表。我可以派生一个新类 DTOList ,我可以在其中重写GetHashCode(). 但这会导致其他地方变得更加复杂。由于 EFCore Set 查询的结果填充列表,我需要一个自定义转换器,然后需要一个自定义序列化器来返回 Web API 中的列表。

因此,我想知道是否应该为 List 创建一个扩展方法,或者只是一个以 List 作为参数的函数。还有其他选项可以计算 ETag 吗?如何有效计算 DTO 对象列表的 ETag?

Jer*_*ert 7

一些扩展方法HashCode可以帮助解决这个问题:

internal static class EnumerableExtensions {
    public static int GetCombinedHashCode<T>(this IEnumerable<T> source) => 
        source.Aggregate(typeof(T).GetHashCode(), (hash, t) => HashCode.Combine(hash, t));
}
Run Code Online (Sandbox Code Playgroud)

散列的种子typeof(T).GetHashCode是相当任意的,但可以确保不同类型的空集合并不都“看起来相等”,因为它们通常也不会比较相等。这是否重要或什至是可取的将取决于您的情况。

当然,只有在T具有有意义的GetHashCode实现的情况下,此结果才可用,但对于一般的散列来说也是如此。为了更加安心,where T : IEquatable<T>可以添加约束,尽管这不是涉及哈希的方法的标准方法。添加使用自定义哈希值的功能IEqualityComparer<T>留作练习。