String.Normalizeとカタカナの複合文字

.NET Frameworkの2.0からですがStringクラスにNormalize というメソッドが付いたことをご存知の方も多いかと思います。Unicodeの文字列を正規化するものですが、日本語にも若干影響があるので、確認の意味を含めてカタカナでの半濁点の動作を検証してみようと思います。

コードは簡単に以下のようなものだとお考えください。

 string[] sa = {
  "ポ", 
   "ホ゜", 
  "ホ\u309a",
  "ポ",
   "\u333d"
};
foreach(string source in sa)
{ 
    string normalized = source.Normalize(); 
    Console.Write("{0}\t", normalized); 
    
    foreach(ch in normalized)
   {
       Console.Write("U+{0:x4} ", Convert.ToUInt16(ch)); 
  }
   Console.WriteLine(); 
}   
   

いろいろと問題はあるかと思いますが、とりあえず、簡略するために仮想的に上のようなコードだとお考えいただくことにします。 ここで、一般的な表記として、カタカナにはいわゆる全角と半角があるのは、ご理解いただけると思いますが、ほかにも複合文字用の半濁点(U+309A: COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK) や独立した半濁点(U+309C: KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK)などを組み合わせると上記のような配列で良いかと思います。引数をもたないNormalize() メソッドはFormCという正規化を行い以下のような出力が得られます。

U+30dd
ホ゜ U+30db U+309c
U+30dd
ポ U+ff8e U+ff9f
U+333d

3番目の要素であった "ホ\u309A" が、1番目の要素と同じカタカナの「ポ (U+30dd)」になる複合の処理が行われます。NormalizaionForm 列挙体のもつ4つの値を同様にforeachなどで繰り返すと以下のような表を作ることができます。

Source FormC FormD FormKC FormKD
U+30dd U+30dd ポ U+30db U+309a U+30dd ポ U+30db U+309a
ホ゜ U+30db U+309c ホ゜ U+30db U+309c ホ゜ U+30db U+309c ホ ゚ U+30db U+0020 U+309a ホ ゚ U+30db U+0020 U+309a
ポ U+30db U+309a U+30dd ポ U+30db U+309a U+30dd ポ U+30db U+309a
ポ U+ff8e U+ff9f ポ U+ff8e U+ff9f ポ U+ff8e U+ff9f U+30dd ポ U+30db U+309a
U+333d U+333d U+333d ポイント U+30dd U+30a4 U+30f3 U+30c8 ポイント U+30db U+309a U+30a4 U+30f3 U+30c8

正規化のフォームは「C」が複合するための "Compose" で「D」が分解のための "Decompose"、「K」は互換性の "Compatible" からよく似た発音を採ったものですが、なかなか動きを理解するのはやっかいな感じがします。

これを、みなさんの実際の開発現場にあてはめて考えて見ましょう。たぶん、システム開発の中では「ここは半角に」、「ここは全角で」という要求なり仕様なりがあると思いますが、WindowsはUnicodeを使っているので、半角や全角という概念は画面上での表面的な描画でしかありません。しかし、開発者でない方には文字を矩形に収めるという要求がごく一般にあるのではないかと思います。また、外部システムで特定の文字セットのみが使える場合など、情報の欠落がないままになんとかしたいという方向で話が進むのではないかと思います。使用可能な文字セットとして半角があれば、上記のテーブルの中ではFormCが妥当かと思いますが、ない場合はFormKCでしょうか。しかし、複合用の半濁点(U+309a) を持たない文字セットのシステムの場合などは、どうするべきかといった懸念があり、必ずしも上手く行くようには思えません。わずらわしいので全てをUnicodeにしてしまうという選択肢もあるかと思いますが、現場の制約から、必ずしもそういかないのが現実ではないかと思います。

最後の「ポイント」を一文字であらわしたものなどはUnicodeだと互換性のためにありますが、ほかにも丸付きの文字や、元号などいろいろとありますので、お試しください。

なお、ここで使用したU+333dを含め、いくつかの互換性の文字は、環境によっては正しく表示されない可能性がありますが、どうかご了承ください。