Почему FxCop предупреждает о переполнении (CA2233) в этом коде C#?

У меня есть следующая функция для получения int из старшего и младшего байтов:

public static int FromBytes(byte high, byte low)
{
    return high * (byte.MaxValue + 1) + low;
}

Когда я анализирую сборку с помощью FxCop, я получаю следующее критическое предупреждение:

CA2233: OperationsShouldNotOverflow
Арифметические операции не должны выполняться без предварительной проверки операндов для предотвращения переполнения.

Я не понимаю, как это могло переполниться, поэтому я просто предполагаю, что FxCop переусердствует.
Я что-то упустил? И какие шаги можно предпринять, чтобы исправить то, что у меня есть (или, по крайней мере, убрать предупреждение FxCop!)?


person Matthew King    schedule 15.04.2010    source источник
comment
Моя ставка на byte.MaxValue + 1 часть.   -  person Mark Carpenter    schedule 15.04.2010
comment
Ваша ставка неверна. Его код не может вызвать переполнение, поскольку byte.MaxValue ВСЕГДА будет неявно преобразован в int до того, как произойдет шаг добавления. -- Каждый раз, когда метод выполняет арифметическую операцию и не проверяет заранее операнды (для предотвращения переполнения), вы получите CA2233. В MSDN есть множество примеров того, как это исправить: msdn.microsoft.com. /en-us/library/ms182354.aspx   -  person BrainSlugs83    schedule 09.01.2012


Ответы (4)


Как Дэниел А. Уайт указано, вы получите сообщение, потому что "(byte.MaxValue + 1)" переполняет байт.

Но вместо приведения и умножения я бы просто сдвинул биты, как это сделано в коде ниже:

public static int FromBytes(byte high, byte low) {
    return high << 8 | low;
}

В качестве побочного эффекта этот код, вероятно, будет работать лучше. Я не проверял полученный IL или x86, чтобы убедиться, что компилятор и/или JITter достаточно умны, чтобы оптимизировать исходное выражение.

person Alfred Myers    schedule 05.05.2010
comment
Опять же, byte.MaxValue + 1 не приводит к переполнению байта. Он получает сообщение, потому что не проверяет свои операнды. Это исчезает для вашего кода, поскольку ваш код не выполняет никакой арифметики, а только двоичную логику. См. msdn.microsoft.com/en-us/library/ms182354.aspx для более подробной информации. - person BrainSlugs83; 09.01.2012

Он делает их как байтовые вычисления.

Попробуй это

return (int)high * ((int)byte.MaxValue + 1) + (int)low;
person Daniel A. White    schedule 15.04.2010
comment
Я как раз собирался это написать! Красиво и быстро. :) - person Joshua; 15.04.2010
comment
-1! (если бы я мог!) Это неправильно. Вам не нужно приводить byte.MaxValue к целому числу — когда вы добавляете целое число и байт — байт АВТОМАТИЧЕСКИ приводится к целому числу — в этом весь смысл неявного преобразования. Для доказательства обратите внимание: public static int GetValue() { return Byte.MaxValue + 1 } возвращает значение 256. Byte + Int = Int. Также обратите внимание, что предоставленный вами код не снимет предупреждение CA2233 FxCop. Просто (i + 1) (где i — целое число) вызовет это предупреждение. - person BrainSlugs83; 09.01.2012

Сложение байтов и множественные результаты представляют собой целые числа. Максимальное значение здесь равно 65535, что не приведет к переполнению целого числа. Просто подавите ошибку.

byte a = 1;
byte b = 2;
object obj = a + b

obj имеет тип int

Попробуй это:

        byte high = 255;
        byte low = 255;
        checked
        {
            int b = high * (byte.MaxValue + 1) + low;   
        }

Без проблем.

или попробуйте это

person csaam    schedule 15.04.2010

Вот 2 способа, которыми он, наконец, перестал ныть о CA2233 для меня:

    public static int FromBytes(byte high, byte low)
    {
        int h = high;
        return h * (byte.MaxValue + 1) + low;
    }

    public static int FromBytes2(byte high, byte low)
    {
        unchecked
        {
            return high * (byte.MaxValue + 1) + low;
        }
    }

Я думаю, что это может быть ошибка в правиле.

person xofz    schedule 15.04.2010