别误用IsDigit与IsNumber函数
1、起因
最近发现程序中有一段控制TextBox数字输入的代码,相信大家都不会太陌生,如下:
void int_KeyPress(object sender, KeyPressEventArgs e)
{
const char Delete = (char);
if (!Char.IsDigit(e.KeyChar) && e.KeyChar != Delete)
{
e.Handled = true;
}
}
乍一看,好像没有啥问题,但是却出现了一个bug,能够输入全角的数字,如:0、1、2、3等。错误的根源就是上面代码中用到的IsDigit函数,于是就有了下面的一番探究,让我们来看看IsDigit函数的真面目。
2、IsDigit函数
查阅MSDN,告知该函数是判断字符是Unicode的十进制数字的函数。在查看其源代码
public static bool IsDigit(char c)
{
if (!IsLatin1(c)) return CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.DecimalDigitNumber;
return c >= '' && c <= '';
}
第一行的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函数又是何物?
先看看这个函数的定义
public static bool IsNumber(char c)
{
if (!IsLatin1(c)) return CheckNumber(CharUnicodeInfo.GetUnicodeCategory(c));
if (!IsAscii(c)) return CheckNumber(GetLatin1UnicodeCategory(c));
return c >= '' && c <= '';
}
internal static bool CheckNumber(UnicodeCategory uc)
{
switch (uc)
{
case UnicodeCategory.DecimalDigitNumber:
case UnicodeCategory.LetterNumber:
case UnicodeCategory.OtherNumber:
return true;
}
return false;
}
和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函数作为结束
void int_KeyPress(object sender, KeyPressEventArgs e)
{
const char Delete = (char);
if (!(e.KeyChar >= '' && e.KeyChar <= '') && e.KeyChar != Delete)
{
e.Handled = true;
}
}
别误用IsDigit与IsNumber函数的更多相关文章
- 别误用IsDigit与IsNumber函数(转)
1.起因 最近发现程序中有一段控制TextBox数字输入的代码,相信大家都不会太陌生,如下: void int_KeyPress(object sender, KeyPressEventArgs e) ...
- Difference between Char.IsDigit() and Char.IsNumber() in C#
http://stackoverflow.com/questions/228532/difference-between-char-isdigit-and-char-isnumber-in-c-sha ...
- 【C#遗补】之Char.IsDigit和Char.IsNumber的区别
原文:[C#遗补]之Char.IsDigit和Char.IsNumber的区别 Char中IsDigit和IsNumber的两个方法都是用来判断字符是否是数字的,那他们有什么区别 IsDigit ...
- isdigit函数
isdigit是计算机应用C语言中的一个函数,主要用于检查参数c是否为阿拉伯数字0到9. 相关函数 isdigit 表头文件 #include <ctype.h>(C语言),#includ ...
- PB函数大全
PB函数大全 Abs()功能计算绝对值.语法Abs ( n )参数n:要得到绝对值的数值型变量或表达式返回值返回值的数据类型与n的数据类型相同,函数执行成功时返回n的绝对值.如果参数n的值为NULL, ...
- C#操作Excel的函数
对于Excel的数据处理功能,大家都已经了解. 我们经常需要将数据导入到Excel,或直接打开Excel文档,读写文件操作,这需要用到ExcelHelper类,有了这个类,这些操作大大的减少我们工作量 ...
- Linux常用C函数---字符测试篇
函数讲解部分参考http://net.pku.edu.cn/~yhf/linux_c/ isalnum(测试字符是否为英文或数字) 相关函数 isalpha,isdigit,islower,isupp ...
- salesforce 零基础学习(六十六)VF页面应善于使用变量和函数(二)常用函数的使用
上一篇介绍VF中常用的变量,此篇主要内容为VF页面可以直接使用的函数,主要包括Date相关函数,Text相关函数,Information相关函数以及logic相关函数,其他相关函数,比如math相关函 ...
- 总结C语言字符检测函数:isalnum、isalpha...
前言:最近一直在刷leetcode的题,用到isalnum函数,用man手册查找了一下,总共有13个相关函数如下: #include <ctype.h> int isalnum(int c ...
随机推荐
- “You must not call setTag() on a view Glide is targeting” 解决
报错原因大致是因为Glide加载的iamgeView调用了setTag()方法导致的错误, 因为Glide已经默认为ImageView设置的Tag. 解决办法:自定义一个Application,在里面 ...
- Tomcat抛出异常:ClientAbortException: java.net.SocketException: Connection
在做一个小网站的时候,写了一个通过servlet实现文件下载功能的页面.当我点击超级练级,弹出下载对话框,点击保存正常下载,不会出现任何问题,当我我点击取消,服务器端就出现如下提示: ClientAb ...
- 基本的文件 I/O
基本的文件 I/O MSDN 抽象基类 Stream 支持读取和写入字节.Stream 集成了异步支持.其默认实现根据其相应的异步方法来定义同步读取和写入,反之亦然. 所有表示流的类都是从 Strea ...
- 解决oracle 端口 1521 本机127可通 其他ip不通
http://wenku.baidu.com/link?url=8tRGGObqgLd6-yqprioIZSyluu9K0BgA29Lhx7F57pVDIHbMHVDNTa_SlEmVugGT4QJO ...
- WPF中如何用代码触发按钮Click处理
btnOk.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
- shell来start、stop、restart应用程序模板
这里使用shell中的case语法: case分支语句格式如下: case $变量名 in 模式1) 命令列表 ;; 模式2) 命令列表 ;; *) ;; esac case行尾必须为单词“in”,每 ...
- mono+jexus 验证码不显示:System.Drawing
System.ArgumentException The requested FontFamily could not be found [GDI+ status: FontFamilyNotFoun ...
- osgi: HttpService A null service reference is not allowed.
最近在学习osgi,在练习HttpService的过程中,一直出现“A null service reference is not allowed”这样的报错,代码本身没有问题,在网上也搜了不少地方, ...
- C++:不同类型的指针的本质与差异
转自:http://blog.csdn.net/richerg85/article/details/10076365 指针的类型(The Type of a Pointer) 一 ...
- java框架篇---spring hibernate整合
在会使用hibernate 和spring框架后 两个框架的整合就变的相当容易了, 为什么要整合Hibernate?1.使用Spring的IOC功能管理SessionFactory对象 LocalSe ...