别误用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,Char.IsDigit 方法是指示某个 Unicode 字符是否属于十进制数字类别。通过ILSpy查看其源代码:
[__DynamicallyInvokable]
public static bool IsDigit(char c)
{
if (char.IsLatin1(c))
{
return c >= '' && c <= '';
}
return CharUnicodeInfo.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]
public static bool IsNumber(char c)
{
if (!char.IsLatin1(c))
{
return char.CheckNumber(CharUnicodeInfo.GetUnicodeCategory(c));
}
if (char.IsAscii(c))
{
return c >= '' && c <= '';
}
return char.CheckNumber(char.GetLatin1UnicodeCategory(c));
}
internal static bool CheckNumber(UnicodeCategory uc)
{
switch (uc)
{
case UnicodeCategory.DecimalDigitNumber:
case UnicodeCategory.LetterNumber:
case UnicodeCategory.OtherNumber:
return true;
default:
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;
}
}
欢迎加群:.NET反编译|破解 群号:183569712(请输入验证信息:博客园). 
引用:
别误用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 ...
随机推荐
- Qt5.3编译错误——call of overloaded ‘max(int int)’is ambiguous
错误描述: 今天在使用Qt写一个C++函数模板的测试程序的时候,编译的时候,编译的时候出现如下错误: 错误描述为:在main函数中,进行函数max()重载时,出现(ambiguous)含糊的,不明确的 ...
- linux奇技淫巧 2
压缩解压==================================================================================== unzip xx.zi ...
- 从零开始用gulp
gulp是基于流的前端构件化工具.目前比较火的前端构建化工具还是挺多的,grunt gulp fis3等等. 这个鬼东西有什么用?请参考https://www.zhihu.com/question/3 ...
- 我心中的核心组件(可插拔的AOP)~分布式文件上传组件~基于FastDFS
回到目录 一些概念 在大叔框架里总觉得缺点什么,在最近的项目开发中,终于知道缺什么了,分布式文件存储组件,就是缺它,呵呵,对于分布式文件存储来说,业界比较公认的是FastDFS组件,它自己本身就是集群 ...
- MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作
一.使用MyBatis对表执行CRUD操作--基于XML的实现 1.定义sql映射xml文件 userMapper.xml文件的内容如下: 1 <?xml version="1.0&q ...
- Atitit 面向对象弊端与问题 坏处 缺点
Atitit 面向对象弊端与问题 坏处 缺点 1.1. 状态fsm,反模块化,又是反并行的,这是它的非常固有的特征, 1 1.2. 现时的OOP编程有可能不缓存友好(cache friendly) ...
- Servlet Filter
Filter : Java中的Filter 并不是一个标准的Servlet ,它不能处理用户请求,也不能对客户端生成响应. 主要用于对HttpServletRequest 进行预处理,也可以对Http ...
- Python的枚举类型
Python的 Python的没有我们有两种用法: 创建Enum的实例 创建Enum的subclass 创建Enum的实例 from enum import Enum, unique Month = ...
- java中变量运算细节 (2)
/* 目的:测试变量的运算方式 结果:byte a, b, c; a = b+c; 或者 a = b+10 形如这种形式的算式, 等式的右边的运算结果默认的都是int型的!因为等式右边有变量, 编译器 ...
- jQuery中$.extend
$.fn是指jquery的命名空间,加上fn上的方法及属性,会对jquery实例每一个有效. 如扩展$.fn.abc(),即$.fn.abc()是对jquery扩展了一个abc方法,那么后面你的每一个 ...