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

时间:2014-02-27 08:53:38

标签: c# .net string character-encoding int

我经常使用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

为什么?我的Char.IsDigit - 通过List<char> digitList = Enumerable.Range(0, UInt16.MaxValue) .Select(i => Convert.ToChar(i)) .Where(c => Char.IsDigit(c)) .ToList(); 预先检查是不正确的吗?

有310个字符是数字:

Char.IsDigit

以下是.NET 4(ILSpy)中public static bool IsDigit(char c) { if (char.IsLatin1(c)) { return c >= '0' && c <= '9'; } return CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.DecimalDigitNumber; } 的实现:

int

那么为什么存在属于DecimalDigitNumber-category“十进制数字字符,即0到9范围内的字符......”)的字符,这些字符不能在任何文化中被解析为{{1}}?

2 个答案:

答案 0 :(得分:8)

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

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

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

例如,工作:

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

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

Microsoft文章"How to: Parse Unicode Digits"声明:

  
    

.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();
}

答案 1 :(得分:3)

十进制数字是0到9,但它们在Unicode中有许多表示形式。来自Wikipedia

  

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

.NET仅解析拉丁数字的MSDN specifies

  

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