string.GetHashCode () возвращает разные значения в отладочной версии против выпуска, как мне избежать этого? - PullRequest
6 голосов
/ 23 сентября 2011

К моему удивлению, метод folowing дает другой результат в отладке по сравнению с выпуском:

int result = "test".GetHashCode();

Есть ли способ избежать этого?

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

Почему это происходит?

К вашему сведению, рефлектор дает мне:

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), SecuritySafeCritical]
public override unsafe int GetHashCode()
{
    fixed (char* str = ((char*) this))
    {
        char* chPtr = str;
        int num = 0x15051505;
        int num2 = num;
        int* numPtr = (int*) chPtr;
        for (int i = this.Length; i > 0; i -= 4)
        {
            num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
            if (i <= 2)
            {
                break;
            }
            num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
            numPtr += 2;
        }
        return (num + (num2 * 0x5d588b65));
    }
}

Ответы [ 3 ]

9 голосов
/ 24 сентября 2011

GetHashCode() - это , а не , что вы должны использовать для хеширования строки, почти в 100% случаев.Не зная, что вы делаете, я рекомендую вам использовать настоящий алгоритм хеширования, такой как SHA-1:

using(System.Security.Cryptography.SHA1Managed hp = new System.Security.Cryptography.SHA1Managed()) {
    // Use hp.ComputeHash(System.Text.Encoding.ASCII (or Unicode, UTF8, UTF16, or UTF32 or something...).GetBytes(theString) to compute the hash code.
}

Обновление: для чего-то немного быстрее, есть также SHA1Cng, что значительнобыстрее чем SHA1Managed.

3 голосов
/ 01 августа 2012

Вот лучший подход, который намного быстрее, чем SHA, и вы можете заменить им модифицированный GetHasCode: C # fast hash murmur2

Существует несколько реализаций с разными уровнями «неуправляемости».код, так что если вам нужно полностью управлять, он там и если вы можете использовать небезопасные, он тоже там.

0 голосов
/ 21 августа 2013
    /// <summary>
    /// Default implementation of string.GetHashCode is not consistent on different platforms (x32/x64 which is our case) and frameworks. 
    /// FNV-1a - (Fowler/Noll/Vo) is a fast, consistent, non-cryptographic hash algorithm with good dispersion. (see http://isthe.com/chongo/tech/comp/fnv/#FNV-1a)
    /// </summary>
    private static int GetFNV1aHashCode(string str)
    {
        if (str == null)
            return 0;
        var length = str.Length;
        // original FNV-1a has 32 bit offset_basis = 2166136261 but length gives a bit better dispersion (2%) for our case where all the strings are equal length, for example: "3EC0FFFF01ECD9C4001B01E2A707"
        int hash = length;
        for (int i = 0; i != length; ++i)
            hash = (hash ^ str[i]) * 16777619;
        return hash;
    }

Я полагаю, что эта реализация медленнее, чем небезопасная, опубликованная здесь . Но это намного проще и безопаснее. Хорошо работает, если суперскорость не нужна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...