Char.IsNumber/GetNumericValue

【VB.NET】指定した文字が数字かどうか判定する(IsDigit, IsNumber, IsNumeric)を見ていて、Char.GetNumericValueとint.Parse/TryParseに違いがあるのかどうかが気になったので試してみた。

using System;

class NumericTest
{
  public static void Main()
  {
    Console.OutputEncoding = System.Text.Encoding.UTF8;
    
    Char[] num = {
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
      '鄯', '鄱', '鄴', '?', '?', '?', '?', '?', '㈠', '㈡',
      '㈩', '⑴', '⒇', '❶', '❿', '➀', '➉', '㊀', '㊁', '㊉',
      '⒈', '⒛', '➊', '➓', '¹', '⁹', '₁', '₉', '〇', '一', '九',
      '零', '壱', '弐', '玖'};
      
    foreach (Char c in num)
    {
      int v;
      if (!int.TryParse(c.ToString(), out v))
        v = -1;
      
      Console.WriteLine(
        "{0}\tIsDigit:{1}\tIsNumber:{2}\tGetNumericValue:{3}\tParse:{4}",
        c, Char.IsDigit(c), Char.IsNumber(c),
        Char.GetNumericValue(c), v);
    }
  }
}

はてながUnicode対応じゃないせいで、見にくいことになってるけど、本当は、

f:id:espresso3389:20111030184307p:image

結論から言うと、おそらく、Char.IsDigitがtrueな場合には、int.Parseも動く。一方で、Char.IsNumberがtrueでも、int.Parseできるとは限らないが、Char.GetNumericValueは数値の値を返してくれるようだ。
ただ、じゃぁ、数値解析ルーチンは、Char.GetNumericValueを使えば良いかといえば、こいつは、漢数字とかローマ数字まで相手にしてしまうので、状況に応じて判断するしかないだろう。

全角の数字文字列を処理したいだけだったら、NFKD・NFKCあたりで正規化してからint.Parseするのが良いかも。

と思ったけど、やっぱり、Char.IsDigitでチェックして、int.Parseというのには問題があるようだ。

http://blogs.msdn.com/b/oldnewthing/archive/2004/03/09/86555.aspx

結局、

static bool isDigit(Char c) { return c >= '0' && c <= '9'; }

なんていうベタなのが順当らしい・・・。