简单示例:
public class SomeClass
{
public string Str1 { get; set; }
public string Str2 { get; set; }
public string Str3 { get; set; }
public string Str4 { get; set; }
public byte[] SHA256()
{
using (var sha256 = new SHA256Managed())
{
var strings = new[] { Str1, Str2, Str3, Str4 };
for (int i = 0; i < strings.Length; i++)
{
string str = strings[i];
if (str != null)
{
// Commented lines are for using ToUpperInvariant()
//str = str.ToUpperInvariant()
byte[] length2 = BitConverter.GetBytes(str.Length);
sha256.TransformBlock(length2, 0, length2.Length, length2, 0);
// byte[] sortKeyBytes = Encoding.UTF8.GetBytes(str);
byte[] sortKeyBytes = CultureInfo.InvariantCulture.CompareInfo.GetSortKey(str, CompareOptions.IgnoreCase).KeyData;
sha256.TransformBlock(sortKeyBytes, 0, sortKeyBytes.Length, sortKeyBytes, 0);
}
else
{
byte[] length2 = BitConverter.GetBytes(-1);
sha256.TransformBlock(length2, 0, length2.Length, length2, 0);
}
}
sha256.TransformFinalBlock(new byte[0], 0, 0);
byte[] hash = sha256.Hash;
return hash;
}
}
}
我正在使用 SHA256,该解决方案基于 @usr 在 https://stackoverflow.com/a/10452967/613130 中建议的解决方案。生成的哈希码长 32 个字节,但您可以将其截断为 20(显然您会降低其唯一性)。
我将各种字符串的长度添加到字符串中。这样{ "ABCD", "", "", "" } 将产生与{ "A", "B", "C", "D" } 不同的哈希值。
如果您愿意,您可以使用旧的 ToUpperInvariant() 并基于它进行散列(代码中有一些注释行...您取消注释它们,删除 byte[] sortKeyBytes = CultureInfo.InvariantCulture 并快乐生活:-))。
我不得不说实话,我不确定GetSortKey 的“稳定性”...GetSortKey 在 .NET 10.0 和 Unicode 11.0 中会在 5 年内返回相同的权重吗?谁知道?我当然不会!
MSDN 建议他们可以改变:
如果应用程序对 SortKey 对象进行序列化,当 .NET Framework 有新版本时,应用程序必须重新生成所有排序键。
所以最后我建议基于.ToUpperInvariant() 的替代解决方案(要明确,如果我的老板让我这样做,我会告诉他:使用.ToUpperInvariant())。请注意,即使使用.ToUpperInvariant(),将来也可能会有一些小的变化。可以为现有的小写字符引入新的大写字符。见http://unicode.org/faq/casemap_charprop.html“如果一对已经编码,可以添加一个case对吗?”