2

s2 は正規化された s1 です。
文字列 s1 と s2 は同じように見えますが、
s1 と s2 の GetHashCode は異なり
ます 。

文字列としての s2 にはアクセントがあります
s2.ToCharArray はアクセントを削除します

s2.ToCharArray が文字列としての s2 と異なるのはなぜですか?

私はそれを考え出した。
s2 の長さは 4 です。
アクセントは別の文字 (Int16 = 769) として取り除かれます。
String.Compare はそれを理解するのに十分賢いです。

興味深いのは、String.Compare はそれを計算しますが、String.Contains は計算しないということです。

string s1 = "xxé";
string s1copy = "xxé";
string s2 = s1.Normalize(NormalizationForm.FormD);
string s2b = "xxe";
char accent = 'é';

Debug.WriteLine(s1);  // xxé
Debug.WriteLine(s2);  // xxé
Debug.WriteLine(s2b); // xxe

Debug.WriteLine(s1.GetHashCode());      // 424384421
Debug.WriteLine(s1copy.GetHashCode());  // 424384421
Debug.WriteLine(s2.GetHashCode());      // 1057341801
Debug.WriteLine(s2b.GetHashCode());     // 1701495145

Debug.WriteLine(s1.Contains(accent));   // true
Debug.WriteLine(s2.Contains(accent));   // false
Debug.WriteLine(s2b.Contains(accent));  // false

Debug.WriteLine(string.Compare(s1, s1copy).ToString());  // 0
Debug.WriteLine(string.Compare(s1, s2).ToString());      // 0
Debug.WriteLine(string.Compare(s1, s2b).ToString());     // 1
Debug.WriteLine(string.Compare(s2, s2b).ToString());     // 1

Debug.WriteLine(s1.Equals(s1copy));  // true
Debug.WriteLine(s1.Equals(s2));      // false
Debug.WriteLine(s1.Equals(s2b));     // false
Debug.WriteLine(s2.Equals(s2b));     // false

Debug.WriteLine(s1 == s1copy);  // true
Debug.WriteLine(s1 == s2);      // false
Debug.WriteLine(s1 == s2b);     // false
Debug.WriteLine(s2 == s2b);     // false

char[] chars1  = s1.ToCharArray();
char[] chars2  = s2.ToCharArray();
char[] chars2b = s2b.ToCharArray();
Debug.WriteLine(chars1.Length.ToString());  // 3
Debug.WriteLine(chars2.Length.ToString());  // 4
Debug.WriteLine(chars2b.Length.ToString()); // 3
Debug.WriteLine(chars1[0].ToString() + " "  + ((Int16)chars1[0]).ToString() + " "  + chars1[1].ToString() + " "  + ((Int16)chars1[1]).ToString() + " "  + chars1[2].ToString() + " "  + ((Int16)chars1[2]).ToString());
// x 120 x 120 é 233
Debug.WriteLine(chars2[0].ToString() + " " + ((Int16)chars2[0]).ToString() + " " + chars2[1].ToString() + " " + ((Int16)chars2[1]).ToString() + " " + chars2[2].ToString() + " " + ((Int16)chars2[2]).ToString() +" " + chars2[3].ToString() + " " + ((Int16)chars2[3]).ToString());  
//x 120 x 120 e 101 ́ 769
Debug.WriteLine(chars2b[0].ToString() + " " + ((Int16)chars2b[0]).ToString() + " " + chars2b[1].ToString() + " " + ((Int16)chars2b[1]).ToString() + " " + chars2b[2].ToString() + " " + ((Int16)chars2b[2]).ToString()); 
//x 120 x 120 e 101
Debug.WriteLine(chars1.GetHashCode());   // 16098066
Debug.WriteLine(chars2.GetHashCode());   // 53324351
Debug.WriteLine(chars2b.GetHashCode());  // 50785559
Debug.WriteLine(chars1 == chars2);  // false
Debug.WriteLine(chars1 == chars2b); // false
Debug.WriteLine(chars2 == chars2b); // false
4

1 に答える 1

3

s2.ToCharArray が文字列としての s2 と異なるのはなぜですか?

これは、NormalizationForm選択した が原因で発生します。xxe、および`に分解xxéされます

NormalizationForm.FormD :

完全正規分解を使用して Unicode 文字列が正規化されることを示します。

これでも不明な場合は、Unicode 構成の定義を次に示します。

Unicode のコンテキストでは、文字合成とは、ベース文字のコード ポイントとそれに続く 1 つ以上の結合文字のコード ポイントを 1 つの合成済み文字に置き換えるプロセスです。文字分解は逆のプロセスです。

基本的に、文字列を最も低い形式 (表示されている 4 つの異なる文字) に分解しています。

組み換えてみると分かりやすいかもchar[]

var s2Compare = new string(chars2)
var isEq = (s2Compare == s2) //true
于 2013-10-10T16:23:30.990 に答える