简述C#中类型转换的方式
数据转换有很多类
1.Convert.ToInt32()
2.as Class1
3.int.Parse()、int.TryParse()字符串转各类型
4.强转 (int)onj
1.Convert.
Convert类是专门进行类型转换的类,它能够实现各种基本数据类型之间的相互转换。
Convert类常用的类型转换方法
方法说明
Convert.ToInt32()转换为整型(int)
Convert.ToChar()转换为字符型(char)
Convert.ToString()转换为字符串型(string)
Convert.ToDateTime()转换为日期型(datetime)
Convert.ToDouble()转换为双精度浮点型(double)
Conert.ToSingle()转换为单精度浮点型(float)
使用Convert类转换数据类型
using System;
using System.Collection.Generic;
using System.Linq;
using System.Text;
namespace Shujuleixingzhuanhuan
{
class Lizi
{
static void Main(string[] args)
{
float num1=82.26f;
int integer,num2;
string str,strdate;
DateTime mydate=DateTime.New;
//Convert类的方法进行转换
integer=Convert.ToInt32(num1);
str=Convert.ToString(num1);
strdate=Convert.ToString(mydate);
num2=Convert.ToInt32(mydate);
Console.WriteLine("转换为整型数据的值{0}",integer);
Console.WriteLine("转换为字符串{0},str");
Console.WriteLine("日期型数据转换为字符串值为{0}",strdate);
Console.ReadKey();
}
}
}
提示 转换为int型数据后进行了四舍五入的计算。
用convert类转换时注意数据表达方式的有效性,并不是任意类型之间都可以转换。
as用法总结 在程序中,进行类型转换时常见的事,C#支持基本的强制类型转换方法,例如 Object obj1 = new NewType();NewType newValue = (NewType)obj1;这样强制转换的时候,这个过程是不安全的,因此需要用try-catch语句进行保护,这样一来,比较安全的代码方式应如下所示:Object obj1 = new NewType();NewType newValue = null;try{newValue = (NewType)obj1;}catch (Exception err){MessageBox.Show(err.Message);}但是上面的写法在C#中已是过时的写法,也是比较低效的写法,比较高效且时尚的写法是用as操作符,如下:Object obj1 = new NewType();NewTYpe newValue = obj1 as NewType;安全性:as操作符不会做过的转换操作,当需要转化对象的类型属于转换目标类型或者转换目标类型的派生类型时,那么此转换操作才能成功,而且并不产生新的对象【当不成功的时候,会返回null】。因此用as进行类型转换是安全的。效率:当用as操作符进行类型转换的时候,首先判断当前对象的类型,当类型满足要求后才进行转换,而传统的类型转换方式,是用当前对象直接去转换,而且为了保护转换成功,要加上try-catch,所以,相对来说,as效率高点。需要注意的是,不管是传统的还是as操作符进行类型转换之后,在使用之前,需要进行判断转换是否成功,如下:if(newValue != null){//Work with the object named “newValue“}但是,使用as操作符要注意以下几点:1、不用在类型之间进行类型转化,即如下编写就会出现编译错误。NewType newValue = new NewType();NewTYpe1 newValue = newValue as NewTYpe1;2、不能应用在值类型数据,即不能如下写(也会出现编译错误)Object obj1 = 11;int nValue = obj1 as int;对于1.,可以用传统的类型转换方式完成:NewTypeOne newTestOne = new NewTypeOne();NewTypeTwo newTestTwo = (NewTypeTwo)newTestOne;要想使上面的操作正确完成,在原有类型中增加类型转换操作符函数,即需要完成类似如下的代码:public calss NewTypeOne{public static explicit operator NewTypeTwo( NewTypeOne obj1){//Convert object into new type}}对于2,在C#中可以使用is操作符,再加上老式的类型转换操作,就可以安全完成转换,要完成如上操作,正确的写法如下:Object obj1 = 11;if(objTest is int ){int nValue = (int)obj1;}在C#中提供的很好的类型转换方式总结为:Object => 已知引用类型——使用as操作符完成;Object => 已知值类型——先使用is操作符来进行判断,再用类型强转换方式进行转换;已知引用类型之间转换——首先需要相应类型提供转换函数,再用类型强转换方式进行转换;已知值类型之间转换——最好使用系统提供的Conver类所涉及的静态方法。
2. as
在程序中,进行类型转换时常见的事,C#支持基本的强制类型转换方法,例如
Object obj1 = new NewType();
NewType newValue = (NewType)obj1;
这样强制转换的时候,这个过程是不安全的,因此需要用try-catch语句进行保护,这样一来,比较安全的代码方式应如下所示:
Object obj1 = new NewType();
NewType newValue = null;
try
{
newValue = (NewType)obj1;
}
catch (Exception err)
{
MessageBox.Show(err.Message);
}
但是上面的写法在C#中已是过时的写法,也是比较低效的写法,比较高效且时尚的写法是用as操作符,如下:
Object obj1 = new NewType();
NewTYpe newValue = obj1 as NewType;
安全性:
as操作符不会做过的转换操作,当需要转化对象的类型属于转换目标类型或者转换目标类型的派生类型时,那么此转换操作才能成功,而且并不产生新的对象【当不成功的时候,会返回null】。因此用as进行类型转换是安全的。
效率:
当用as操作符进行类型转换的时候,首先判断当前对象的类型,当类型满足要求后才进行转换,而传统的类型转换方式,是用当前对象直接去转换,而且为了保护转换成功,要加上try-catch,所以,相对来说,as效率高点。
需要注意的是,不管是传统的还是as操作符进行类型转换之后,在使用之前,需要进行判断转换是否成功,如下:
if(newValue != null)
{
//Work with the object named “newValue“
}
但是,使用as操作符要注意以下几点:
1、不用在类型之间进行类型转化,即如下编写就会出现编译错误。
NewType newValue = new NewType();
NewTYpe1 newValue = newValue as NewTYpe1;
2、不能应用在值类型数据,即不能如下写(也会出现编译错误)
Object obj1 = 11;
int nValue = obj1 as int;
对于1.,可以用传统的类型转换方式完成:
NewTypeOne newTestOne = new NewTypeOne();
NewTypeTwo newTestTwo = (NewTypeTwo)newTestOne;
要想使上面的操作正确完成,在原有类型中增加类型转换操作符函数,即需要完成类似如下的代码:
public calss NewTypeOne
{
public static explicit operator NewTypeTwo( NewTypeOne obj1)
{
//Convert object into new type
}
}
对于2,在C#中可以使用is操作符,再加上老式的类型转换操作,就可以安全完成转换,要完成如上操作,正确的写法如下:
Object obj1 = 11;
if(objTest is int )
{
int nValue = (int)obj1;
}
在C#中提供的很好的类型转换方式总结为:
Object => 已知引用类型——使用as操作符完成;
Object => 已知值类型——先使用is操作符来进行判断,再用类型强转换方式进行转换;
已知引用类型之间转换——首先需要相应类型提供转换函数,再用类型强转换方式进行转换;
已知值类型之间转换——最好使用系统提供的Conver类所涉及的静态方法。
3.int.Parse()、int.TryParse()字符串转各类型
(2)int.Parse方法的参数如果不能转换为整数,则报异常。
如 int c=int.Parse("2.8"); //报异常,说明其参数必须是整数字符串
//int.TryParse
int c = -1;
int.TryParse("2.8", out c); //不能转换成功,结果为0
int.TryParse("2", out c); //转换成功,结果为2
那么,当要转换的信息为一个字符而不是数字的时候又怎么样呢?
结果如下所示:
int a = (int)'a'; //结果为97,注意是字符,而不是字符串(如果是字符串,编译不能通过)
int b = Convert.ToInt32("a"); //报异常
int c=int.Parse("a"); //报异常
int d = -1;
int.TryParse("a", out d); //结果为0
4.强制类型转换
int a=1;
object b=a;
int c=(int)b;
强制类型转换需要注意,被转类型与目标类型之间必须兼容,另外就是装箱和拆箱的问题
装箱和拆箱是值类型和引用类型之间相互转换是要执行的操作。
1. 装箱在值类型向引用类型转换时发生
2. 拆箱在引用类型向值类型转换时发生
光上述两句话不难理解,但是往深处了解,就需要一些篇幅来解释了。
我们先看装箱时都会发生什么事情,下面是一行最简单的装箱代码
object obj = 1;
这行语句将整型常量1赋给object类型的变量obj; 众所周知常量1是值类型,值类型是要放在栈上的,而object是引用类型,它需要放在堆上;要把值类型放在堆上就需要执行一次装箱操作。
这行语句的IL代码如下,请注意注释部分说明:
.locals init (
[0] object objValue
) //以上三行IL表示声明object类型的名称为objValue的局部变量
IL_0000: nop
IL_0001: ldc.i4.s 9 //表示将整型数9放到栈顶
IL_0003: box [mscorlib]System.Int32 //执行IL box指令,在内存堆中申请System.Int32类型需要的堆空间
IL_0008: stloc.0 //弹出堆栈上的变量,将它存储到索引为0的局部变量中
以上就是装箱所要执行的操作了,执行装箱操作时不可避免的要在堆上申请内存空间,并将堆栈上的值类型数据复制到申请的堆内存空间上,这肯定是要消耗内存和cpu资源的。我们再看下拆箱操作是怎么回事:
请看下面的C#代码:
object objValue = 4;
int value = (int)objValue;
上面的两行代码会执行一次装箱操作将整形数字常量4装箱成引用类型object变量objValue;然后又执行一次拆箱操作,将存储到堆上的引用变量objValue存储到局部整形值类型变量value中。
同样我们需要看下IL代码:
.locals init (
[0] object objValue,
[1] int32 'value'
) //上面IL声明两个局部变量object类型的objValue和int32类型的value变量
IL_0000: nop
IL_0001: ldc.i4.4 //将整型数字4压入栈
IL_0002: box [mscorlib]System.Int32 //执行IL box指令,在内存堆中申请System.Int32类型需要的堆空间
IL_0007: stloc.0 //弹出堆栈上的变量,将它存储到索引为0的局部变量中
IL_0008: ldloc.0//将索引为0的局部变量(即objValue变量)压入栈
IL_0009: unbox.any [mscorlib]System.Int32 //执行IL 拆箱指令unbox.any 将引用类型object转换成System.Int32类型
IL_000e: stloc.1 //将栈上的数据存储到索引为1的局部变量即value
拆箱操作的执行过程和装箱操作过程正好相反,是将存储在堆上的引用类型值转换为值类型并给值类型变量。
装箱操作和拆箱操作是要额外耗费cpu和内存资源的,所以在c# 2.0之后引入了泛型来减少装箱操作和拆箱操作消耗。
其余参考