Нужна дополнительная помощь в преобразовании функции CRC из VB.NET в C#.

Я, наверное, должен был просто поместить все это в один вопрос, извините за это :(

Вторая ошибка

Хорошо, это должен быть конец ошибок (надеюсь):

private static string getCRC(string input, bool appendDate)
{
    string toEnc = string.Format("{0}{1}", input, appendDate == true ? string.Format("{0:yyyyMMdd}", System.DateTime.Now) : "");
    System.IO.MemoryStream mStream = new System.IO.MemoryStream(System.Text.ASCIIEncoding.ASCII.GetBytes(toEnc), false);
    
    CRC32 oCRC = new CRC32();
    return oCRC.GetCrc32(((System.IO.Stream)mStream)).ToString();
}

Ошибка на обратной линии:

Сообщение об ошибке компилятора: CS1502: лучшее совпадение перегруженного метода для «CRC.CRC32.GetCrc32(ref System.IO.Stream)» содержит недопустимые аргументы.

Вот функция, на которую он ссылается:

public UInt32 GetCrc32(ref System.IO.Stream stream)
{
    //Dim crc32Result As Integer = &HFFFFFFFF
    UInt32 crc32Result = UInt32.MaxValue;

    try
    {

        byte[] buffer = new byte[BUFFER_SIZE];
        int readSize = BUFFER_SIZE;

        int count = stream.Read(buffer, 0, readSize);
        int i;
        UInt32 iLookup;
        //Dim tot As Integer = 0
        while ((count > 0))
        {
            for (i = 0; i <= count - 1; i++)
            {
                iLookup = (crc32Result & 0xff) ^ buffer[i];
                //crc32Result = ((crc32Result And &HFFFFFF00) \ &H100) And &HFFFFFF                     ' nasty shr 8 with vb :/
                crc32Result = ((UInt32)((crc32Result & 4294967040L) / 256) & UInt32.MaxValue);
                // nasty shr 8 with vb :/
                crc32Result = crc32Result ^ crc32Table[iLookup];
            }
            count = stream.Read(buffer, 0, readSize);
        }
    }
    catch (Exception ex)
    {
        HttpContext.Current.Response.Output.Write(string.Format("{0}{1}{2}", ex.Message, Environment.NewLine, ex.StackTrace));
        System.Diagnostics.Debugger.Break();
    }

    return (~crc32Result);

}

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

Первая ошибка

(решено здесь)

Если вы не видели пару моих последних вопросов, у меня есть функция CRC, написанная на VB.NET. Я использовал онлайн-конвертер, чтобы преобразовать его в C#. Вот исходный код VB:

Public Sub New()
    Dim dwPolynomial As UInt32 = 3988292384
    Dim i As Integer, j As Integer

    ReDim crc32Table(256)
    Dim dwCrc As UInt32

    For i = 0 To 255
        dwCrc = i
        For j = 8 To 1 Step -1
            If (dwCrc And 1) Then
                dwCrc = ((dwCrc And &HFFFFFFFE) \ 2&) And &H7FFFFFFF
                dwCrc = dwCrc Xor dwPolynomial
            Else
                dwCrc = ((dwCrc And &HFFFFFFFE) \ 2&) And &H7FFFFFFF
            End If
        Next j
        crc32Table(i) = dwCrc
    Next i
End Sub

Вот мой преобразованный код. Я исправил несколько ошибок, которые у меня были, но есть еще несколько, которые я не могу понять:

public CRC32()
{
    UInt32 dwPolynomial = ((UInt32)3988292384L);
    int i;
    int j;

    UInt32[] crc32Table;
    crc32Table = new UInt32[256];
    UInt32 dwCrc;

    for (i = 0; i <= 255; i++)
    {
        dwCrc = ((UInt32)i);
        for (j = 8; j >= 1; j -= 1)
        {
            if ((dwCrc & 1))
            {
                dwCrc = ((dwCrc & 0xfffffffe) / 2L) & 0x7fffffff;
                dwCrc = dwCrc ^ dwPolynomial;
            }
            else
            {
                dwCrc = ((dwCrc & 0xfffffffe) / 2L) & 0x7fffffff;
            }
        }
        crc32Table[i] = dwCrc;
    }
}

Первая ошибка в этой строке:

Сообщение об ошибке компилятора: CS0030: невозможно преобразовать тип uint в bool.

if ((dwCrc & 1))

Должен ли я сравнивать эти два значения с другим оператором? Честно говоря, я не слишком уверен в том, зачем нужен оператор &.

Спасибо ТАК.


person Anders    schedule 24.07.2009    source источник
comment
В вашем коде VB.NET есть ошибка. ReDim crc32Table(256) дает вам 25 * 7 * записей, но вы заполняете только 256. Преобразование испортило его (правильным эквивалентом C # будет новый uint [257]), но на самом деле он подходит для вашего случая. ;)   -  person Mark Brackett    schedule 25.07.2009


Ответы (6)


В C# нет неявного преобразования целых чисел в логические. Вы должны сравнить с 0 явно:

if ((dwCrc & 1) != 0) ...
person Pavel Minaev    schedule 24.07.2009

C# не предполагает, что 0 равно false, а 1 равно true.

Таким образом

if ((dwCrc & 1) == 1) { }

Было бы то, что вам нужно.

person Claus Jørgensen    schedule 24.07.2009

Для вашей второй проблемы (которая получила бы больше трафика, если бы вы опубликовали ее как второй вопрос):

Лучший перегруженный метод, соответствующий «CRC.CRC32.GetCrc32 (ref System.IO.Stream)», имеет некоторые недопустимые аргументы.

Удалите модификатор ref в коде C#:

public UInt32 GetCrc32(ref System.IO.Stream stream)

становится

public UInt32 GetCrc32(System.IO.Stream stream)

Я подозреваю, что исходный VB.NET имел ByRef там, где это не было необходимо - я не вижу, чтобы вы где-либо переназначали значение stream.

В качестве альтернативы вызовите его с параметром ref:

return oCRC.GetCrc32(ref mStream).ToString();
person Mark Brackett    schedule 24.07.2009

С помощью ReSharper я скомпилировал ваш преобразованный код.

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

    public void CRC32()
    {
        UInt32 dwPolynomial = ((UInt32) 3988292384L);
        int i;
        int j;

        UInt32[] crc32Table;
        crc32Table = new UInt32[256];
        UInt32 dwCrc;

        for (i = 0; i <= 255; i++)
        {
            dwCrc = ((UInt32) i);
            for (j = 8; j >= 1; j -= 1)
            {
                if ((dwCrc & 1) != 0u)
                {
                    dwCrc = (uint) (((dwCrc & 0xfffffffe)/2L) & 0x7fffffff);
                    dwCrc = dwCrc ^ dwPolynomial;
                }
                else
                {
                    dwCrc = (uint) (((dwCrc & 0xfffffffe)/2L) & 0x7fffffff);
                }
            }

            crc32Table[i] = dwCrc;
        }
    }
person Paul Sasik    schedule 24.07.2009

Эта конкретная строка выполняет побитовое И с dwCrc и 1, что равно 0x01. По сути, это проверка того, что младший значащий бит dwCrc равен 1, а не 0. Если это так, результатом будет 1. Если нет, результатом будет 0. В VB целые числа автоматически преобразуются в логические значения (0 -> false , все остальное -> верно). В C# вы должны явно сравнивать его со значением

if ((dwCrc & 1) != 0) ...

(Также обратите внимание, что ( & 1) предположительно необходим, так как он проверяет только один конкретный бит. Если dwCrc == 0x02, то исходный тест завершится ошибкой, как и преобразованный. Поэтому делаем что-то вроде

if(dwCrc != 0) ...

было бы неправильно, хотя на первый взгляд может показаться, что это не так.)

person Sean    schedule 24.07.2009

Похоже, что многие из этих ответов касаются вашей первой ошибки. Проблема с вашей второй ошибкой заключается в том, что ваш метод GetCrc ожидает, что поток будет передан по ссылке (ключевое слово ref).

В C#, если метод определяет параметр по ссылке, вы должны явно передать его по ссылке при вызове. Поэтому добавьте ключевое слово ref при вызове GetCrcMethod:

(также вам не нужно приведение — MemoryStream наследуется от Stream)

return oCrc.GetCrc32(ref mStream).ToString();

Еще одно соображение: если вы не планируете изменить ссылку на поток mStream, вам не нужно создавать параметр byRef. Если вы не планируете присваивать значение потоку (поток = новый поток или поток = ноль), правильнее просто вообще удалить ключевое слово ref из объявления метода.

person JMarsch    schedule 24.07.2009