4、结论

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

1、起因最近发现程序中有一段控制TextBox数字输入的代码,相信大家都不会太陌生,如下:

voidint_KeyPRess(objectsender, KeyPressEventArgs e)

{constcharDelete = (char)8;if(!Char.IsDigit(e.KeyChar) && e.KeyChar !=Delete)

{

e.Handled=true;

}

}

乍一看,好像没有啥问题,但是却出现了一个bug,能够输入全角的数字,如:0、1、2、3等。错误的根源就是上面代码中用到的IsDigit函数,于是就有了下面的一番探究,让我们来看看IsDigit函数的真面目。

2、IsDigit函数查阅MSDN,Char.IsDigit 方法是指示某个 Unicode 字符是否属于十进制数字类别。通过ILSpy查看其源代码:

[__DynamicallyInvokable]publicstaticboolIsDigit(charc)

{if(char.IsLatin1(c))

{returnc >='0'&& c <='9';

}returnCharUnicodeInfo.GetUnicodeCategory(c) ==UnicodeCategory.DecimalDigitNumber;

}

第一行的IsLatin1函数是判断字符是0~255的函数,而全角的0、1、2、3等的Unicode编码不在这个范围,于是就执行了下面这句代码:

CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.DecimalDigitNumber;

而对于Unicode的分类中,半角的1,2,3和全角的0、1、2、3等都被归为了DecimalDigitNumber,所以对于全角的数字,这个函数返回了true。

还有一个函数IsNumber和IsDigit功能相似,我们是否可以用它来代替呢?看下面的分析

3、IsNumber函数又是何物?MSDN的解释:Char.IsNumber 方法指示某个 Unicode 字符是否属于数字类别。

这个函数的定义:

[__DynamicallyInvokable]publicstaticboolIsNumber(charc)

{if(!char.IsLatin1(c))

{returnchar.CheckNumber(CharUnicodeInfo.GetUnicodeCategory(c));

}if(char.IsAscii(c))

{returnc >='0'&& c <='9';

}returnchar.CheckNumber(char.GetLatin1UnicodeCategory(c));

}

internalstaticboolCheckNumber(UnicodeCategory uc)

{switch(uc)

{caseUnicodeCategory.DecimalDigitNumber:caseUnicodeCategory.LetterNumber:caseUnicodeCategory.OtherNumber:returntrue;default:returnfalse;

}

}

和IsDigit函数相比有3点区别:

1)多了一个UnicodeCategory.LetterNumber类型

2)多了一个UnicodeCategory.OtherNumber类型

3)多了一个IsAscii的判断(0~127)

很显然IsNumber的范围更广了。下面列举几种IsNumber认为是数字的字符

UnicodeCategory.LetterNumber:Ⅰ、Ⅱ、Ⅲ

UnicodeCategory.OtherNumber:①、②、③

128~255中有哪些字符会被IsNumber认为是数字,有兴趣的可以自己去测试。

测试的方法可以利用这个函数:System.Globalization.CharUnicodeInfo.GetUnicodeCategory(char c) ,返回的是一个UnicodeCategory类型,你可以看看是不是IsNumber的几个类型就知道了。

4、结论搞清楚了上面这两个函数的内部实现,那么在判断是否是ASCII数字(0~9)的时候,我们就需要注意以下几点了。

1)不能用IsDigit和IsNumber函数判断是否是ASCII数字,这两个函数都有可能把ASCII以外的某些字符当做是数字。

2)尽量用这种方式判断: c >= '0' && c <= '9'(当然也可以用正则表达式)。

3)数字判断的严格性,从严到松依次是:

c >= '0' && c <= '9'⇒IsDigit ⇒IsNumber

4)修改上面的bug函数作为结束

voidint_KeyPress(objectsender, KeyPressEventArgs e)

{constcharDelete = (char)8;if(!(e.KeyChar >='0'&& e.KeyChar <='9') && e.KeyChar !=Delete)

{

e.Handled=true;

}

}

欢迎加群:.NET反编译|破解 群号:183569712(请输入验证信息:博客园).

引用:

别误用IsDigit与IsNumber函数

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航