Битовый или оператор, используемый для операнда с расширенным знаком в Visual Studio 2015

Я только что попытался установить Visual Studio 2015, и при попытке скомпилировать старый проект, я получил предупреждение

CS0675 Битовый или оператор, используемый в операнде с расширенным знаком; сначала рассмотрите приведение к меньшему типу без знака

для фрагмента кода, который не выдает того же предупреждения при компиляции в Visual Studio 2013. Я обнаружил, что все, что требуется для воспроизведения, это очень простой код:

short a = 0;
int b = 0;

a |= (short)b;

Теперь я прочитал этот вопрос, я прочитал сообщение Эрика Липперта в блоге по этой проблеме, и я быстро прочитал о расширении знака, но я понимаю, что расширение знака происходит, когда вы применяете тип числа со знаком, состоящий из меньшего числа. битов в один с большим количеством битов, таких как short в int например.

Но так как я кастую из int к short Расширение знака не должно произойти, если я не ошибаюсь. Тот факт, что это не выдает предупреждение в более ранних версиях Visual Studio, приводит меня к мысли, что это должно быть ошибкой в ​​компиляторе Visual Studio 2015 (Roslyn). Я неправильно понимаю, как расширение знака и / или компилятор работает здесь, или это, скорее всего, ошибка компилятора?

Обновить

Джон Скит отметил, что на самом деле расширение знака происходит с | оператор не определен для short и поэтому есть неявное приведение к int прежде чем результат будет возвращен к short снова. Тем не менее, компилятор не должен был выдавать это предупреждение, поскольку приведение безвредно. Была ошибка в компиляторе Roslyn, как указано в принятом ответе.

2 ответа

Решение

Это просто ошибка. Код для обнаружения и сообщения об этой ошибке был добавлен очень поздно в разработке VS2015 (см. https://github.com/dotnet/roslyn/issues/909 и https://github.com/dotnet/roslyn/pull/2416). и он обнаруживает слишком много случаев по сравнению с VS2013. Теперь есть сообщение об ошибке ( https://github.com/dotnet/roslyn/issues/4027), чтобы исправить это.

Расширение знака происходит, но, возможно, не по очевидной причине, и не в тревожном смысле, IMO.

Этот код:

a |= (short) b;

эквивалентно:

// No warning here... (surprisingly, given that `a` is being sign-extended...)
a = (short) (a | (short) b);

Что эквивалентно:

// No warning here...
a = (short) ((int) a | (int) (short) b;

поскольку | оператор не определен для short операнды в любом случае. Оба операнда повышены до int затем результат возвращается к short,

Непонятно, почему компилятор решает предупредить в этом случае, но происходит расширение знака... хотя и безвредно.

Обратите внимание, что вы получите то же предупреждение, если нет int переменные задействованы вообще:

short a = 10;
short b = 20;
a |= b; // CS0675

Учитывая то, что | оператор работает с приведениями, это выглядит для меня совершенно безобидно. Я не уверен, назову ли я это ошибкой компилятора, но это определенно выглядит как неидеальное поведение для меня. Будет пинговать членов команды C#, чтобы увидеть, что я пропустил:)

Другие вопросы по тегам