Для чего используется ключевое слово С#?

Я впервые встретил это ключевое слово. Что он делает, и когда он должен использоваться?

int multiply(int i, int j)
{
    return checked(i * j);
}

Ответы

Ответ 1

У Эрика Липперта есть запись в блоге из двух частей: "Для чего нужно ключевое слово без контроля?": Часть 1 - Часть 2


"Проверено" - это ключевое слово блока, которое включает проверку арифметического переполнения. Обычно, если целочисленная операция превышает максимальное или минимальное значение, которое может обрабатывать тип, операция все равно продолжается, и результат просто повторяется, как одометр. Так, например:

byte b = byte.MaxValue;
Console.WriteLine(b);       // 255  (11111111)
Console.WriteLine(++b);     // 0    (00000000)

Помещение этого фрагмента в 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
    }
}

А так как есть опция компилятора /checked, которая включает проверку компилятора по умолчанию, есть также ключевое слово unchecked которое предотвращает проверку переполнения.


Что касается использования, проверка переполнения должна использоваться экономно, как и в случае обработки исключений в целом. Чтобы проверить переполнение во время выполнения, он значительно быстрее (например, на порядок) выполняет простую проверку, а не включает проверку переполнения:

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

Вы можете сделать это даже для 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;
}

Там также есть хорошая статья о проекте кода, которая объясняет некоторые предостережения (например, проверка переполнения применяется только к непосредственному блоку кода, а не к каким-либо вызовам функций внутри блока).