为什么Char.IsDigit对于无法解析为int的字符返回true?

我经常使用Char.IsDigit检查char是否是一个数字,在LINQ查询中特别方便,以预先检查int.Parse如下所示: "123".All(Char.IsDigit)

但是有些字符是数字,但不能像۵一样解析为int

 // true bool isDigit = Char.IsDigit('۵'); var cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures); int num; // false bool isIntForAnyCulture = cultures .Any(c => int.TryParse('۵'.ToString(), NumberStyles.Any, c, out num)); 

这是为什么? 我的int.Parse -precheck是否通过Char.IsDigit错误?

有310个字符是数字:

 List digitList = Enumerable.Range(0, UInt16.MaxValue) .Select(i => Convert.ToChar(i)) .Where(c => Char.IsDigit(c)) .ToList(); 

这是.NET 4(ILSpy)中Char.IsDigit的实现:

 public static bool IsDigit(char c) { if (char.IsLatin1(c)) { return c >= '0' && c <= '9'; } return CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.DecimalDigitNumber; } 

那么为什么存在属于DecimalDigitNumber -category的 字符“十进制数字字符,即0到9之间的字符……” ),这些字符在任何文化中都无法解析为int

这是因为它正在检查Unicode“Number,Decimal Digit”类别中的所有数字,如下所示:

http://www.fileformat.info/info/unicode/category/Nd/list.htm

这并不意味着它是当前语言环境中的有效数字字符。 事实上,使用int.Parse() ,您只能解析正常的英文数字,​​无论语言环境设置如何。

例如,这不起作用

 int test = int.Parse("٣", CultureInfo.GetCultureInfo("ar")); 

即使٣是有效的阿拉伯数字字符,“ar”也是阿拉伯语区域设置标识符。

微软文章“如何:解析Unicode数字”指出:

.NET Framework作为小数分析的唯一Unicode数字是ASCII数字0到9,由代码值U + 0030到U + 0039指定。 .NET Framework将所有其他Unicode数字解析为字符。

但请注意,您可以使用char.GetNumericValue()将unicode数字字符转换为数字等效字符作为double。

返回值是double而不是int的原因是因为这样的事情:

 Console.WriteLine(char.GetNumericValue('¼')); // Prints 0.25 

您可以使用类似的东西将字符串中的所有数字字符转换为ASCII等效字符:

 public string ConvertNumericChars(string input) { StringBuilder output = new StringBuilder(); foreach (char ch in input) { if (char.IsDigit(ch)) { double value = char.GetNumericValue(ch); if ((value >= 0) && (value <= 9) && (value == (int)value)) { output.Append((char)('0'+(int)value)); continue; } } output.Append(ch); } return output.ToString(); } 

十进制数字为0到9,但它们在Unicode中有许多表示forms。 来自维基百科 :

十进制数字在23个单独的块中重复

MSDN 指定 .NET仅解析拉丁数字:

但是,解析方法识别的唯一数字是基本的拉丁数字0-9,代码点从U + 0030到U + 0039