C # Небезопасный перевод кода? - PullRequest
3 голосов
/ 11 января 2012

У меня есть код, который я использую в стандартном приложении C #.

Я делюсь библиотекой в ​​проекте Silverlight, который не допускает небезопасного кода. Я совсем немного знаю о небезопасной / логике / арифметике указателей, и мне было интересно, может ли кто-нибудь перевести следующий фрагмент кода, чтобы он работал без / unsafe. Меня не волнует падение производительности, так как код не будет часто вызываться на клиенте. Заранее благодарим за любую помощь.

    public static unsafe int GeStableHash(string name)
    {
        fixed (char* str = name)
        {
            char* chPtr = str;
            int num = 352654597;
            int num2 = num;
            int* numPtr = (int*)chPtr;
            for (int i = name.Length; i > 0; i -= 4)
            {
                num = (((num << 5) + num) + (num >> 27)) ^ numPtr[0];
                if (i <= 2)
                {
                    break;
                }
                num2 = (((num2 << 5) + num2) + (num2 >> 27)) ^ numPtr[1];
                numPtr += 2;
            }
            return (num + (num2 * 1566083941));
        }
    }

Согласно ответу ниже, я изучил реализацию этой функции в Silverlight.

Теперь я еще больше запутался. Код, который я вижу в строке SL mscorlib.dll. Функция GetHashCode выглядит следующим образом (она использует ключевое слово unsafe и дает синтаксические ошибки в Visual Studio!):

[SecuritySafeCritical, ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public unsafe override int GetHashCode()
{
    IntPtr arg_0F_0;
    IntPtr expr_06 = arg_0F_0 = this;
    if (expr_06 != 0)
    {
        arg_0F_0 = (IntPtr)((int)expr_06 + RuntimeHelpers.OffsetToStringData);
    }
    char* ptr = arg_0F_0;
    int num = 352654597;
    int num2 = num;
    int* ptr2 = (int*)ptr;
    int i;
    for (i = this.Length; i > 2; i -= 4)
    {
        num = ((num << 5) + num + (num >> 27) ^ *ptr2);
        num2 = ((num2 << 5) + num2 + (num2 >> 27) ^ ptr2[(IntPtr)4 / 4]);
        ptr2 += (IntPtr)8 / 4;
    }
    if (i > 0)
    {
        num = ((num << 5) + num + (num >> 27) ^ *ptr2);
    }
    return num + num2 * 1566083941;
}

Решение можно найти здесь: https://codereview.stackexchange.com/questions/7661/c-unsafe-code-translation

Ответы [ 3 ]

1 голос
/ 11 января 2012

Реализации хеш-кода, которые вы опубликовали, используют арифметику указателей для повышения производительности. Он компилируется в Visual Studio, если поместить его в проект .NET Framework с параметром «разрешить небезопасный код».

Можно было бы вычислить тот же результат, используя ту же логику, но непосредственно индексируя строку. Например, выражение "Hello, World"[7] оценивается как 'W'.

Я оставлю сам перевод в качестве пресловутого упражнения для читателя.

1 голос
/ 11 января 2012

Похоже, что это реализация GetHashCode

Так что, возможно, вам не нужно ничего делать "datatohash" .GetHashCode ();будет достаточно

0 голосов
/ 11 января 2012

Почему бы вам не сделать что-то вроде MD5 хэша? Он стабилен и реализован в разных местах.

...