为什么VS 2017在没有未经检查的块的情况下生成GetHashCode

问题描述 投票:2回答:2

我最近发现Visual Studio 2017可以自动生成EqualsGetHashCode的覆盖,但我想知道为什么GetHashCode实现不在unchecked块中?

我创建了一个带有两个公共字符串属性Foo和Bar的简单类,生成的GetHashCode实现如下所示。

public override int GetHashCode()
{
    var hashCode = -504981047;
    hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Foo);
    hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Bar);
    return hashCode;
}

我认为GetHashCode实现的未经检查是非常重要的,因为它很可能会溢出,我们不希望任何溢出异常,因为它很好,如果它环绕。

c# visual-studio visual-studio-2017 gethashcode
2个回答
2
投票

默认情况下,C#项目不检查溢出和下溢。

右键单击项目,选择Properties,在底部的Build选项卡上选择Advanced...,选中标记为Check for arithmetic overflow/underflow的框

现在默认行为是抛出System.OverflowException,如果有明显的unchecked块中没有溢出。

如果为项目启用溢出检查自动生成EqualsGetHashCode的覆盖,则未经检查的块将按预期进行

public override int GetHashCode()
{
    unchecked
    {
        var hashCode = -504981047;
        hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Foo);
        hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Bar);
        return hashCode;
    }
}

1
投票

显然,我对没有检查与未检查vs检查的理解是有缺陷的。编写一些简单的测试以查看此fiddle中的溢出行为非常简单。

快速摘要如下:

如果运行没有明确的检查

  • 如果编译器可以轻松而静态地确定代码将溢出,则会出现编译错误。
  • 如果在运行时出现溢出,则不会抛出任何溢出异常。

如果显式未选中运行

  • 编译器将允许明显溢出的代码
  • 不会抛出运行时溢出异常

如果运行明确检查

  • 如果编译器可以轻松而静态地确定代码将溢出,则会出现编译错误。
  • 如果在运行时出现溢出,则会抛出System.OverflowException

所以...我想从所有这一切的教训是,如果你有一些可能会溢出的计算,并且你关心溢出,将它放在checked块中是非常重要的。如果你有可能溢出的代码,并且你不关心溢出,显然你可以跳过未经检查的块(除非你的代码显然会从静态分析的角度溢出)。

来自小提琴的代码也被复制到这里以供后代使用。

using System;

public class Program
{
    public static void Main()
    {
        var rand = new Random();
        int test = 0;

        //obscured enough that the compiler doesn't "know" that the line will produce an overflow
        //Does not run explicitly as checked, so no runtime OverflowException is thrown
        test = rand.Next(Int32.MaxValue-2, Int32.MaxValue) + 10;

        //simple enough that the compiler "knows" that the line will produce an overflow
        //Compilation error (line 16, col 10): The operation overflows at compile time in checked mode
        //test = Int32.MaxValue + 1;

        //Explicitly running as unchecked. Compiler allows line that is "known" to overflow.
        unchecked
        {
            test = Int32.MaxValue + 1;
        }

        Console.WriteLine(test);

        //Explicitly running as unchecked. Still no runtime OverflowException
        unchecked
        {
            test = test - 10;   
        }

        Console.WriteLine(test);

        //Explicitly running as checked. System.OverflowException: Arithmetic operation resulted in an overflow.
        checked
        {
            test = test + 10;
        }

        Console.WriteLine(test);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.