什么是C#"checked"关键字?

McG*_*gle 31 c#

我第一次遇到这个关键字.它做什么,什么时候应该使用?

int multiply(int i, int j)
{
    return checked(i * j);
}
Run Code Online (Sandbox Code Playgroud)

McG*_*gle 58

Eric Lippert有一个由两部分组成的博客文章"什么是未经检查的关键词有用?":第1 部分 - 第2部分


"Checked"是一个块关键字,用于启用算术溢出检查.通常,如果整数运算超过该类型可以处理的最大值或最小值,则无论如何都会进行操作,结果就像里程表一样循环.所以,例如:

byte b = byte.MaxValue;
Console.WriteLine(b);       // 255  (11111111)
Console.WriteLine(++b);     // 0    (00000000)
Run Code Online (Sandbox Code Playgroud)

将此代码段放在checked块中可防止溢出,而运行时会抛出OverflowException:

checked
{
    byte b = byte.MaxValue;
    Console.WriteLine(b);               // b=255
    try
    {
        Console.WriteLine(++b);
    }
    catch (OverflowException e)
    {
        Console.WriteLine(e.Message);   // "Arithmetic operation resulted in an overflow." 
                                        // b = 255
    }
}
Run Code Online (Sandbox Code Playgroud)

由于有一个编译器选项/checked,默认情况下会打开编译器检查,还有unchecked一个阻止溢出检查的关键字.


就使用情况而言,应谨慎使用溢出检查,一般情况下也应使用异常处理.要在运行时检查溢出,进行简单检查要快得多(比如一个数量级),而不是打开溢出检查:

int multiply(int i, int j)
{ 
    if ((long)i * (long)j > int.MaxValue)
        throw new InvalidOperationException("overflow");
    return i*j;
}
Run Code Online (Sandbox Code Playgroud)

即使对于Int64/long,您也可以使用BigInteger(这仍然比使用速度快至少一个数量级checked):

long multiply(long i, long j)
{ 
    if (new System.Numerics.BigInteger(i) + j > long.MaxValue)
        throw new InvalidOperationException("overflow");
    return i*j;
}
Run Code Online (Sandbox Code Playgroud)

还有一篇很好的Code Project文章解释了一些注意事项(例如,溢出检查仅适用于直接代码块,而不适用于块内的任何函数调用).

  • 你确定它实际上更快吗?因为我运行的基准似乎不同意 (3认同)
  • 我在发布版本的本地机器上写了这个代码 https://dotnetfiddle.net/P6brPu 并检查似乎总是更快 (2认同)