数据类型转换与进制转换
2.5.1 数值类型转换
数值类型转换分为两种:隐式转换、强制转换(显式转换)。
隐式转换
只要能保证值不会发生改变,类型转换就可以自动(隐式)进行。所以,只能从较小的整数类型隐式的转换为较大的整数类型。
1 static void Main(string[] args) 2 { 3 byte b = 24;//byte类型,8位无符号整数 4 int i = 100;//int类型,32位无符号整数 5 double d = 30.3;//double类型,64位双精度浮点数 6 7 i = b;//byte --> int 可以进行隐式转换 8 d = i;//int --> double 可以进行隐式转换 9 10 //i = d;//double --> int 不能隐式转换,会发生数据丢失(丢失小数部分) 11 //b = i;//int --> byte 不能隐式转换,会发生数据丢失(丢失3个字节的数据) 12 }
但是有一中比较特殊的情况:
1 static void Main(string[] args) 2 { 3 byte num1 = 20; 4 byte num2 = 10; 5 6 short sh1 = 30; 7 short sh2 = 40; 8 9 char ch1 = 'a'; 10 char ch2 = 'b'; 11 12 13 //byte res1 = num1 + num2;//错误:无法将类型int隐式转化为int 14 //short res2 = sh1 + sh2;//错误:无法将类型int隐式转化为short 15 //char res3 = ch1 + ch2;//错误:无法将类型int隐式转化为char 16 17 int res1 = num1 + num2;//正确 18 int res2 = sh1 + sh2;//正确 19 int res3 = ch1 + ch2;//正确 20 21 Console.WriteLine(res1 + ":" + res2 + ":" + res3);//30:70:195 22 Console.ReadKey(); 23 }
我们从错误可以推断出,byte、short、char类型的数值求和结果的类型为int类型,而不再是他们本身的类型了,为什么会出现这种情况呢?
原因是byte、short类型所表示的数值的范围比较小,例如,byte类型只能表示0-255的整数,两个byte类型的数字相加,很有可能就超出了byte类型的表示范围;所以当程序运行时,会将结果的类型隐式的转换为int类型;此时如果将结果赋值给一个int类型的变量,自然就会报错。
显式转换
有时我们需要进行类型转换,即时知道可能存在数据丢失的情况,例如将double类型的数值转换为int类型;此时,我们就需要使用显式转换,或者叫强制类型转换。
显式类型转换就是在需要转换的类型前面通过一对(),为其指定要转换的目标类型:
1 static void Main(string[] args) 2 { 3 int num1 = 30; 4 double num2 = 40.49; 5 6 num1 = (int)num2; 7 8 Console.WriteLine(num1);//40 9 10 Console.ReadKey(); 11 }
但是,所有的显式类型转换都是可能不安全的。
1 static void Main(string[] args) 2 { 3 long num1 = 3000000000; 4 int num2 = (int)num1; 5 6 Console.WriteLine(num2);//-1294967296 7 8 Console.ReadKey(); 9 }
当进行long和int类型的转换时,如果long类型的数值,比int类型所能表示的最大值还大,就会出现上边的情况。所以在应用程序中应该包含代码来处理可能失败的类型转换。
C#提供了一个checked运算符,使用它可以测试操作是否会导致算数溢出,可以检查类型强制转换是否安全,如果不安全,就可以抛出一个异常。
1 static void Main(string[] args) 2 { 3 long num1 = 3000000000; 4 int num2; 5 checked 6 { 7 num2 = (int)num1;//异常:算术运算导致溢出 8 } 9 10 Console.WriteLine(num2); 11 12 Console.ReadKey(); 13 }
用户自定义的类型强制转换
C#允许进行两种不同数据类型的强制转换:隐式强制转换和显式强制转换。
如果源数据值会使类型强制转换失败,后者可能会抛出异常,就应把任何自定义的类型强制转换定义为显式强制转换;并且不能同时定义隐式强制类型转换和显示强制类型转换。
定义类型强制转换的语法类似于重载运算符,下面的代码定义了隐式强制类型转换(implicit)。
1 class Boy 2 { 3 public string name; 4 public int age; 5 public Boy(string name, int age) 6 { 7 this.name = name; 8 this.age = age; 9 } 10 /// <summary> 11 /// 定义 Boy-->Girl 的隐式强制类型转换方式 12 /// </summary> 13 /// <param name="boy">源类型</param> 14 /// <returns></returns> 15 public static implicit operator Girl(Boy boy) 16 { 17 return new Girl(boy.name, boy.age); 18 } 19 /// <summary> 20 /// 定义 Girl --> Boy 的隐式强制类型转换方式 21 /// </summary> 22 /// <param name="girl">源类型</param> 23 /// <returns></returns> 24 public static implicit operator Boy(Girl girl) 25 { 26 return new Boy(girl.name, girl.age); 27 } 28 } 29 30 class Girl 31 { 32 public string name; 33 public int age; 34 public Girl(string name, int age) 35 { 36 this.name = name; 37 this.age = age; 38 } 39 } 40 41 class Program 42 { 43 static void Main(string[] args) 44 { 45 Boy boy = new Boy("张三", 20); 46 Girl girl = boy; 47 48 Girl g = new Girl("李四", 30); 49 Boy b = g; 50 51 Console.WriteLine(girl.name + ":" + girl.age); 52 Console.WriteLine(b.name + ":" + b.age); 53 54 Console.ReadKey(); 55 } 56 }
定义显式强制类型转换,代码如下(explicit):
1 class Boy 2 { 3 public string name; 4 public int age; 5 public Boy(string name, int age) 6 { 7 this.name = name; 8 this.age = age; 9 } 10 } 11 12 class Girl 13 { 14 public string name; 15 public int age; 16 public Girl(string name, int age) 17 { 18 this.name = name; 19 this.age = age; 20 } 21 /// <summary> 22 /// 定义 Boy --> Girl 的显式强制类型转换方法 23 /// </summary> 24 /// <param name="boy">源类型</param> 25 /// <returns></returns> 26 public static explicit operator Girl(Boy boy) 27 { 28 return new Girl(boy.name, boy.age); 29 } 30 /// <summary> 31 /// 定义 Girl --> Boy 的显式强制类型转换方法 32 /// </summary> 33 /// <param name="boy">源类型</param> 34 /// <returns></returns> 35 public static explicit operator Boy(Girl girl) 36 { 37 return new Boy(girl.name, girl.age); 38 } 39 } 40 41 class Program 42 { 43 static void Main(string[] args) 44 { 45 Boy boy = new Boy("张三", 20); 46 Girl girl = (Girl)boy; 47 48 Girl g = new Girl("李四", 30); 49 Boy b = (Boy)g; 50 51 Console.WriteLine(girl.name + ":" + girl.age); 52 Console.WriteLine(b.name + ":" + b.age); 53 54 Console.ReadKey(); 55 } 56 }
自定义的类型转换要求放在源类或者目标类中,不可以放在其他地方。
常用的基本类型转换:
源类型 |
目标类型 |
转换方法 |
示例 |
bool、byte、char、double、decimal、float、long、short、sbyte、string、int、ulong、ushort |
int |
Convert.ToInt32(Type value) |
int num = Convert.ToInt32("30"); |
string |
int |
int.Parse(string s) |
int num = int.Parse("20"); |
string |
int |
int.TryPase(string s,out int result) |
int num = 0; if (int.TryParse("20", out num)) { //类型转化成功,变量num中的值为20; } else { //类型转化失败,变量num中的值为0; } |
bool、byte、char、DateTime、decimal、double、float、int、long、sbyte、short、uint、ulong、ushort |
string |
Type.ToString() |
ushort sh = 9; Console.WriteLine(sh.ToString()); |
char[] |
string |
new string() |
char[] ch = new char[] { 'a', 'b', 'c','d' }; string str = new string(ch); |
byte[] |
string |
Encoding.Default.GetString() |
byte[] by = { 97, 98, 99, 100 }; string str = Encoding.Default.GetString(by); |
byte、decimal、double、float、int、long、sbyte、short、string、uint、ulong、ushort |
bool |
Convert.ToBoolean() |
string str = "false"; int i = 20;//零为False,非零为True bool bo = Convert.ToBoolean(str); bool bo2 = Convert.ToBoolean(i); |
string |
char[] |
s.ToArray(); s.ToCharArray() |
string str = "abcd"; char[] res; res = str.ToArray(); res = str.ToCharArray(); |
byte[] |
char[] |
Encoding.Default.GetChars() |
byte[] by = { 30, 49, 9 }; char[] res = Encoding.Default.GetChars(by); |
string |
byte[] |
Encoding.Default.GetBytes() |
string str = "abcd"; byte[] res = Encoding.Default.GetBytes(str); |
char[] |
byte[] |
Encoding.Default.GetBytes() |
char[] ch = { 'a', 'b', 'c' }; byte[] res = Encoding.Default.GetBytes(ch); |
2.5.2 进制转换
1 //二进制-->十进制 2 Console.WriteLine(Convert.ToInt32("1010", 2));//10 3 //八进制-->十进制 4 Console.WriteLine(Convert.ToInt32("21", 8));//17 5 //十六进制-->十进制 6 Console.WriteLine(Convert.ToInt32("32", 16));//50 7 Console.WriteLine(Convert.ToInt32("0x00000032", 16));//50 8 9 //十进制-->十六进制 10 Console.WriteLine(Convert.ToString(20, 16));//14 11 Console.WriteLine(242.ToString("X"));//F2 12 Console.WriteLine(242.ToString("X8"));//000000F2 13 Console.WriteLine(242.ToString("x"));//f2 14 Console.WriteLine(242.ToString("x8"));//000000f2 15 //十进制-->八进制 16 Console.WriteLine(Convert.ToString(15,8));//17 17 //十进制-->二进制 18 Console.WriteLine(Convert.ToString(10, 2));//1010