Различия в двоичном сдвиге между VB.NET и C # - PullRequest
11 голосов
/ 16 ноября 2011

Я только что обнаружил интересную проблему между переводом некоторых данных:

VB.NET: CByte(4) << 8 Возвращает 4

Но C #: (byte)4 << 8 Возвращает 1024

А именно, почему VB.NET: (CByte(4) << 8).GetType() возвращает тип {Name = "Byte" FullName = "System.Byte"}

Пока что C #: ((byte)4 << 8).GetType() возвращает тип {Name = "Int32" FullName = "System.Int32"}

Есть ли причина, по которой эти двое обрабатывают двоичный сдвиг одинаково? Исходя из этого, есть ли способ заставить битовый сдвиг C # работать так же, как VB.NET (чтобы заставить VB.NET работать так же, как C #, вы просто делаете CInt(_____) << 8)?

Ответы [ 3 ]

11 голосов
/ 16 ноября 2011

Согласно http://msdn.microsoft.com/en-us/library/a1sway8w.aspx байт не имеет << определенного для него C # (только int, uint, long и ulong. Это означает, что он будет использовать имплицитное преобразование в тип, который он может использовать, поэтому онпреобразует его в int перед выполнением сдвига битов. </p>

http://msdn.microsoft.com/en-us/library/7haw1dex.aspx говорит, что VB определяет операцию над байтами. Чтобы предотвратить переполнение, он применяет маску к вашему сдвигу, чтобы привести его в соответствующий диапазон, чтобы онна самом деле в этом случае вообще ничего не сдвигается.

Относительно того, почему C # не определяет сдвиг байтов, я не могу вам сказать.

Чтобы заставить его вести себя одинаково для другихтипы данных, вам нужно просто замаскировать свой номер смены на 7 для байтов или 15 для коротких (см. вторую ссылку для информации).

6 голосов
/ 16 ноября 2011

Крис уже прибил его, vb.net определил операторы сдвига для типов Byte и Short, а C # - нет.Спецификация C # очень похожа на C и также хорошо соответствует определениям MSIL для OpCodes.Shl, Shr и Shr_Un, они принимают только операнды int32, int64 и intptr.Соответственно, любые байты или операнды короткого размера сначала преобразуются в int32 с их неявным преобразованием.

Это ограничение, с которым должен работать компилятор vb.net, он должен генерировать дополнительный код, чтобы сделать байты и короткиеконкретные версии операторов работают.Байт-оператор реализован так:

Dim result As Byte = CByte(leftOperand << (rightOperand And 7))

и оператор короткого вызова:

Dim result As Short = CShort(leftOperand << (rightOperand And 15))

Соответствующая операция C #:

Dim result As Integer = CInt(leftOperand) << CInt(rightOperand)

Или CLng ()если необходимо.В коде C # подразумевается, что программист всегда должен приводить результат к желаемому типу результата.Есть много таких вопросов от программистов, которые не думают, что это очень интуитивно понятно.VB.NET имеет еще одну функцию, которая делает автоматическое приведение более живучим, по умолчанию включена проверка переполнения.Хотя это не относится к сменам.

6 голосов
/ 16 ноября 2011

Чтобы применить то же самое в C #, вы должны использовать

static byte LeftShiftVBStyle(byte value, int count)
{
    return (byte)(value << (count & 7));
}

о том, почему VB выбрал такой подход ... просто другой язык, разные правила (это естественное продолжение того, как C # обрабатывает смещение int / & 31 и long / & 63, если честно).

...