我们从小学就开始知道要数据类型转换,不知道为什么到现在还有程序员在数据类型转换上晕来晕去的。
一头猪+一头羊=?
显然我们要数据类型转换为:(牲口)一头猪+(牲口)一头羊=两头牲口。
在C#中同样如此,在转换中的要领是
大的转小的,隐式转。小的转大的,显示转。
另外一个最重要的要领是,转换的两边必须相等。
这个相等是指数据的两边要么是值类型,要么是引用类型。(关于值类型和引用类型我们下一篇马上出来)
以上代码告诉我们什么是转换的两边必须相等。
那个大到小是什么意思呢?大容量的数据类型转到小容量的数据类型是要付出精度代价的。记住,我们关注的是容量而不是具体的值。
现看一下基础值的容量范围
那么我们来考虑以下代码的输出
你是不是会认为目前b的值就是b能容纳的最大值呢?或者你认为会运行错误?
我们要学点推理和思考。以上代码是不是向我们演示了这样一个过程
double.MaxValue-->long.MaxValue-->int.MaxValue-->short.MaxValue-->byte.MaxValue
看上去似乎是的,但是我们来考虑一段代码
所以刚才代码的演变是
关于数据类型转变,还有一个重要的现象
一头猪+一头羊=?
显然我们要数据类型转换为:(牲口)一头猪+(牲口)一头羊=两头牲口。
在C#中同样如此,在转换中的要领是
大的转小的,隐式转。小的转大的,显示转。
隐式转换 | 适用于那些不用仔细检查即可安全地实现的转换 |
总是会成功,而且从不会导致信息丢失 | |
显式转换 | 换需用强制转换表达式来实现 |
不完全安全,可能会损失精度 | |
强制转换表达式既可用于显式转换亦可用于隐式转换 |
另外一个最重要的要领是,转换的两边必须相等。
这个相等是指数据的两边要么是值类型,要么是引用类型。(关于值类型和引用类型我们下一篇马上出来)
1 int i = 10;
2 int j = i;//赋值的两边都是值类型,成功
3 i = (int)j;//赋值的两边都是值类型,成功
4
5 string n = (string)i;//string是引用类型,int是值类型,两边不平衡。失败
6
7 object o = i;
8 string m = (string)o;//无法将类型为“System.Int32”的对象强制转换为类型“System.String”。失败
9 j = (int)o;//成功
2 int j = i;//赋值的两边都是值类型,成功
3 i = (int)j;//赋值的两边都是值类型,成功
4
5 string n = (string)i;//string是引用类型,int是值类型,两边不平衡。失败
6
7 object o = i;
8 string m = (string)o;//无法将类型为“System.Int32”的对象强制转换为类型“System.String”。失败
9 j = (int)o;//成功
以上代码告诉我们什么是转换的两边必须相等。
那个大到小是什么意思呢?大容量的数据类型转到小容量的数据类型是要付出精度代价的。记住,我们关注的是容量而不是具体的值。
现看一下基础值的容量范围
1 System.Console.WriteLine("byte:{0}<-->{1}", byte.MaxValue, byte.MinValue);
2 System.Console.WriteLine("short:{0}<-->{1}", short.MaxValue, short.MinValue);
3 System.Console.WriteLine("int:{0}<-->{1}", int.MaxValue, int.MinValue);
4 System.Console.WriteLine("long:{0}<-->{1}", long.MaxValue, long.MinValue);
5 System.Console.WriteLine("float:{0}<-->{1}", float.MaxValue, float.MinValue);
6 System.Console.WriteLine("decimal:{0}<-->{1}", decimal.MaxValue, decimal.MinValue);
7 System.Console.WriteLine("double:{0}<-->{1}", double.MaxValue, double.MinValue);
8
9 System.Console.WriteLine("char:{0}<-->{1}", char.MaxValue, char.MinValue);
2 System.Console.WriteLine("short:{0}<-->{1}", short.MaxValue, short.MinValue);
3 System.Console.WriteLine("int:{0}<-->{1}", int.MaxValue, int.MinValue);
4 System.Console.WriteLine("long:{0}<-->{1}", long.MaxValue, long.MinValue);
5 System.Console.WriteLine("float:{0}<-->{1}", float.MaxValue, float.MinValue);
6 System.Console.WriteLine("decimal:{0}<-->{1}", decimal.MaxValue, decimal.MinValue);
7 System.Console.WriteLine("double:{0}<-->{1}", double.MaxValue, double.MinValue);
8
9 System.Console.WriteLine("char:{0}<-->{1}", char.MaxValue, char.MinValue);
那么我们来考虑以下代码的输出
1 double d = double.MaxValue;
2 long l = (long)d;
3 int i = (int)l;
4 short s = (short)i;
5 byte b = (byte)s;
6 System.Console.WriteLine(b);
7 System.Console.WriteLine(b==byte.MaxValue);
2 long l = (long)d;
3 int i = (int)l;
4 short s = (short)i;
5 byte b = (byte)s;
6 System.Console.WriteLine(b);
7 System.Console.WriteLine(b==byte.MaxValue);
你是不是会认为目前b的值就是b能容纳的最大值呢?或者你认为会运行错误?
我们要学点推理和思考。以上代码是不是向我们演示了这样一个过程
double.MaxValue-->long.MaxValue-->int.MaxValue-->short.MaxValue-->byte.MaxValue
看上去似乎是的,但是我们来考虑一段代码
1 byte b = 200;
2 b += 100;
3 System.Console.WriteLine(b);//输出的结果不是255,也不是错误,是44
现在你冷静考虑一下,是不是感觉到了当数据类型获得了超出资金范围的值以后的处理方式了吗?围绕。2 b += 100;
3 System.Console.WriteLine(b);//输出的结果不是255,也不是错误,是44
所以刚才代码的演变是
1 double d = double.MaxValue;// d 1.7976931348623157E+308 double
2 long l = (long)d;//-9223372036854775808
3 int i = (int)l;//0
4 short s = (short)i;//0
5 byte b = (byte)s;//0
6 System.Console.WriteLine(b);
7 System.Console.WriteLine(b == byte.MaxValue);
2 long l = (long)d;//-9223372036854775808
3 int i = (int)l;//0
4 short s = (short)i;//0
5 byte b = (byte)s;//0
6 System.Console.WriteLine(b);
7 System.Console.WriteLine(b == byte.MaxValue);
关于数据类型转变,还有一个重要的现象
1 byte b = 10;
2 b = b + 100;//无法将类型“int”隐式转换为“byte”
3 b += 100;//通过
2 b = b + 100;//无法将类型“int”隐式转换为“byte”
3 b += 100;//通过
原因是+是运算符,运算符的左右要类型一致,所以编译器要转为b=(int)b+100;这样结果就是int了,int比byte大,所以不能直接赋值为b,编译错误。 要改为b =(byte) ((int)b + 100);
而+=和=都是赋值运算,编译会做可能的转换试探。
关于char和int的转换,有C经验的都知道其实他们都一样
1 for (int i = 'a'; i <= 'z'; i++)
2 {
3 char c = (char)i;
4 System.Console.WriteLine(c);
5 }
6
7 for (char c = 'a'; c <= 'z'; c++)
8 {
9 System.Console.WriteLine(c);
10 }
2 {
3 char c = (char)i;
4 System.Console.WriteLine(c);
5 }
6
7 for (char c = 'a'; c <= 'z'; c++)
8 {
9 System.Console.WriteLine(c);
10 }
以上两段代码的效果一样。
初学者对于C#的字符串转数字之类的总感觉很迷惑,int i = (int)"123";使错误的,所以有同学用System.Convert.ToInt32("123");哎,这个也太累了。基础数据其实都提供了字符串的转换能力。
1 System.Console.WriteLine(byte.Parse("123"));
2 System.Console.WriteLine(short.Parse("123"));
3 System.Console.WriteLine(int.Parse("123"));
4 System.Console.WriteLine(long.Parse("123"));
5 System.Console.WriteLine(float.Parse("123"));
6 System.Console.WriteLine(decimal.Parse("123"));
7 System.Console.WriteLine(double.Parse("123"));
2 System.Console.WriteLine(short.Parse("123"));
3 System.Console.WriteLine(int.Parse("123"));
4 System.Console.WriteLine(long.Parse("123"));
5 System.Console.WriteLine(float.Parse("123"));
6 System.Console.WriteLine(decimal.Parse("123"));
7 System.Console.WriteLine(double.Parse("123"));
2005还提供了Tryparse的方法,可以让你不至于出去转换异常。