C #: невозможно преобразовать из ulong в байт - PullRequest
2 голосов
/ 26 марта 2009

Странно, как я могу сделать это в C ++, но не в C #.

Чтобы прояснить ситуацию, я вставлю две функции в C ++, а затем в C # и отмечу проблемные строки в коде C # комментарием "// error". Эти две функции выполняют кодирование параметра и затем добавляют его в глобальную переменную с именем byte1seeds.

Это функции в C ++

//Global var:

unsigned char byte1seeds[3];

unsigned long GenerateValue( unsigned long * Ptr )
{
unsigned long val = *Ptr;
for( int i = 0; i < 32; i++ )
    val = (((((((((((val >> 2)^val) >> 2)^val) >> 1)^val) >> 1)^val) >> 1)^val)&1)|((((val&1) << 31)|(val >> 1))&0xFFFFFFFE);
return ( *Ptr = val );
}

void SetupCountByte( unsigned long seed )
{
if( seed == 0 ) seed = 0x9ABFB3B6;
unsigned long mut = seed;
unsigned long mut1 = GenerateValue( &mut );
unsigned long mut2 = GenerateValue( &mut );
unsigned long mut3 = GenerateValue( &mut );
GenerateValue( &mut );
unsigned char byte1 = (mut&0xFF)^(mut3&0xFF);
unsigned char byte2 = (mut1&0xFF)^(mut2&0xFF);
if( !byte1 ) byte1 = 1;
if( !byte2 ) byte2 = 1;
byte1seeds[0] = byte1^byte2;
byte1seeds[1] = byte2;
byte1seeds[2] = byte1;
}

Теперь код C #:

Я изменил функцию GenerateValue. Вместо указания указателя в качестве параметра он имеет параметр ulong.

Для вызова и изменения обоих значений я использую:

  1. ulong mut1 = GenerateValue (mut);
  2. mut = mut1;

Вот переведенные функции (проблемные строки помечены "// ошибка");

//Global var:
public static byte[] byte1seeds = new byte[3];

public static ulong GenerateValue(ulong val)
{
    for( int i = 0; i < 32; i++ )
        val = (((((((((((val >> 2)^val) >> 2)^val) >> 1)^val) >> 1)^val) >> 1)^val)&1)|((((val&1) << 31)|(val >> 1))&0xFFFFFFFE);
    return val ;
}

public static void SetupCountByte( uint seed )
{
    if( seed == 0 ) seed = 0x9ABFB3B6;
    ulong mut = seed;
    ulong mut1 = GenerateValue(mut);
    mut = mut1;
    ulong mut2 = GenerateValue(mut);
    mut = mut2;
    ulong mut3 = GenerateValue(mut);
    mut = mut3;
    mut = GenerateValue(mut);
    byte byte1 = (mut & 0xFF) ^ (mut3 & 0xFF); //error
    byte byte2 = (mut1 & 0xFF) ^ (mut2 & 0xFF); //error
    if( byte1 != 0 )
        byte1 = 1;
    if( byte2 != 0 )
        byte2 = 1;
    byte1seeds[0] = byte1^byte2; //error
    byte1seeds[1] = byte2;
    byte1seeds[2] = byte1;
}

Ошибка:

Невозможно неявно преобразовать тип 'ulong' в 'byte'. Существует явное преобразование (вам не хватает приведения?)

edit: ошибка в проблемной строке 3:

Невозможно неявно преобразовать тип 'int' в 'byte'. Существует явное преобразование (вам не хватает приведения?)

Здесь возникает вопрос: как решить эти ошибки?

Заранее спасибо!

Ответы [ 5 ]

11 голосов
/ 26 марта 2009

Добавьте (byte), чтобы разыграть его. Поскольку вы можете потерять точность, вы должны сообщить компилятору, что значение будет помещаться в байт, т.е.

byte byte1 = (byte)((mut & 0xFF) ^ (mut3 & 0xFF));
byte byte2 = (byte)((mut1 & 0xFF) ^ (mut2 & 0xFF));
2 голосов
/ 26 марта 2009

Симптом

Следующий код компилируется в C ++, но отклоняется компилятором C # с несовместимостью типов отчетов третьей строки.

ulong mut = 5;
ulong mut3 = 6;
byte foo = (mut & 0xFF) ^ (mut3 & 0xFF);

Объяснение

Выражение (mut & 0xFF) ^ (mut3 & 0xFF) имеет тип ulong и не может быть присвоено переменной типа byte.

Переменная mut представляет собой ulong. Все перегрузки & требуют симметрии типа операнда, поэтому в выражении (mut & 0xFF) значение 0xFF повышается до ulong, а результат операции имеет тип ulong.

Хотя аналогичный процесс также дает второму подвыражению тип ulong, это является случайным, поскольку в большем выражении A ^ B тот факт, что выражение A имеет тип ulong, вызовет выражение B будет повышен.

Таким образом, выражение (mut & 0xFF) ^ (mut3 & 0xFF) имеет тип ulong и требует явного приведения, прежде чем его можно будет присвоить переменной типа byte.

Решение

Явно типизируйте все выражение перед присваиванием.

Примечания

Люди отключают предупреждения вместо того, чтобы думать о них, потому что большинство библиотек C + изобилуют дефектами. Если вы снова включите предупреждения, вы получите так много, что бесполезно пытаться пробраться через них, даже если где-то в этой неразберихе появится примечание о том, что «требуется неявный тип передачи с потерями».

Если вы прочитаете спецификацию языка C #, особенно с учетом операторов, вы узнаете много полезного. Например, этот код не будет работать:

byte b = 0xF0 | 0x0E; //b should contain 0xFE

но это удастся:

byte b1 = (byte)(0xF0 | 0x0E); //typecast fixes it
byte b2 = 0xF0;
b2 |= 0x0E; //reflexive operator typed by target variable
2 голосов
/ 26 марта 2009

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

byte result = ((byte)mut & 0xFF) ^ ((byte)mut3 & 0xFF);

Таким образом, все переменные явно преобразуются, и результат будет байтом. Или вы можете сделать это:

byte result = (byte)((mut & 0xFF) ^ (mut3 & 0xFF));
1 голос
/ 26 марта 2009

В статье базы знаний MSDN подробно объясняется необходимость явного понижения. Слова «явное преобразование существует» в сообщении об ошибке предназначены для указания того, что вы должны явно преобразовать тип данных с помощью приведения. В вашем конкретном случае это будет выглядеть так:

byte byte1 = (byte) ( (mut & 0xFF) ^ (mut3 & 0xFF) );
1 голос
/ 26 марта 2009

«явное преобразование существует» означает, что вам нужно выполнить явное приведение. В этом случае это будет что-то вроде:

byte byte1 = (byte) ( (mut & 0xFF) ^ (mut3 & 0xFF) );
byte byte2 = (byte) ( (mut1 & 0xFF) ^ (mut2 & 0xFF) );
...