【问题标题】:Hash code of string is broken in .NET Core 2.1, but works in 2.0字符串的哈希码在 .NET Core 2.1 中被破坏,但在 2.0 中有效
【发布时间】:2018-10-30 05:08:46
【问题描述】:

我最近将我的一个项目从 .NET Core 2.0 升级到了 .NET Core 2.1。这样做之后,我的几个测试开始失败。

缩小范围后,我发现在 .NET Core 2.1 中,无法使用带有字符串排序比较选项的文化感知比较器来计算字符串的哈希码。

我创建了一个可以重现我的问题的测试:

[TestMethod]
public void Can_compute_hash_code_using_invariant_string_sort_comparer()
{
    var compareInfo = CultureInfo.InvariantCulture.CompareInfo;
    var stringComparer = compareInfo.GetStringComparer(CompareOptions.StringSort);
    stringComparer.GetHashCode("test"); // should not throw!
}

我已经在几个框架上对其进行了测试,结果如下:

  • .NET Core 2.0:✔通过
  • .NET Core 2.1:✖失败
  • .NET Framework 4.7:✖失败
  • .NET Framework 4.6.2:✖失败

当失败时,ArgumentException 会从 CompareInfo.GetHashCodeOfString 抛出,说:

标志值无效

现在,我的问题:

  1. 为什么在计算哈希码时不允许使用CompareOptions.StringSort

  2. 为什么在 .NET Core 2.0 中允许使用它?`

据我了解CompareOptions.StringSort 仅影响字符串的相对排序顺序,不应影响哈希码计算。 MSDN 说:

StringSort 表示字符串比较必须使用字符串排序算法。在字符串排序中,连字符和撇号以及其他非字母数字符号位于字母数字字符之前。

【问题讨论】:

  • 也许是 GitHub 的问题?
  • @TheGeneral 需要详细说明吗?
  • .NET Core 是开源的,位于 GitHub 中,.Net 代码 Jedi 和 oompa loompas 孜孜不倦地工作,让您快乐
  • 让问题保持开放,有人可能会插话,或在您收到回复时更新我们
  • 我投票决定将此问题作为离题结束,因为它是一个错误问题,目前正在 GitHub 上进行跟踪。

标签: c# string .net-core hashcode


【解决方案1】:

corefx 团队有 confirmed 表示这是 .NET Core 2.1 中的一个错误,也是 4.6+ 的完整 .NET Framework 中的一个错误。

他们还承认,在完整框架中很难更改此行为,因此可能会考虑在 .NET Core 2.1+ 中保持原样以保持 .NET Core 与完整框架之间的一致性。

一种可能的解决方法是使用这样的类:

internal sealed class CultureAwareStringSortComparer : StringComparer
{
    public CultureAwareStringSortComparer(
        CompareInfo compareInfo, 
        CompareOptions options = CompareOptions.StringSort)
    {
        Requires.ArgNotNull(compareInfo, nameof(compareInfo));
        this.SortComparer = compareInfo.GetStringComparer(options);
        this.HashCodeComparer = compareInfo.GetStringComparer(
            options & ~CompareOptions.StringSort);
    }

    internal StringComparer SortComparer { get; }

    internal StringComparer HashCodeComparer { get; }

    public override int Compare(string x, string y) => this.SortComparer.Compare(x, y);

    public override bool Equals(string x, string y) => this.SortComparer.Equals(x, y);

    public override int GetHashCode(string obj) => this.HashCodeComparer.GetHashCode(obj);
}

【讨论】:

    猜你喜欢
    • 2016-03-04
    • 1970-01-01
    • 1970-01-01
    • 2018-11-10
    • 1970-01-01
    • 1970-01-01
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多