天天看点

C#-类型转换,is或as进行类型转换及区别,null值,可空值类型 083

作者:源丁编程

基本数据类型转换

C#的基本数据进行类型转换分两种:

1)隐式(自动)类型转换:两种数据类型可以兼容(相容)并且由小向大的进行转换

2)强制(显示)类型转换:1)两种数据类型可以兼容并且由大向小转换 2)通过方法进行强制转换

//隐式(自动)类型转换,从内存级别上考虑
系统会自动将小的向大的转换
这里的小与大指的是数据类型可以表示的存储容量
int a=1;
float b =a;//变量a赋值给b后隐式转换为float
double c=b;//变量b赋值给c后隐式转换为double
//=======================================
//强制类型转换
1)两者可以兼容
double a = 1;
float b = (float)a;
int c = (int)b
2)根据数据意义进行强制转换
string num1 ="123";
int num2= Convert.ToInt32(num1);//123
int num3 = int.Parse(num1);//123
int num5 =0;
int.TryParse(num1, out num5);//123
Parse与TryParse的区别:,
示例: int a = int.Parse("kk");
Parse会报异常"输入字符串的格式不正确"

示例:int b =8;   int.TryParse("kk",out b);
结果 为 0
TryParse不会报异常 

bool a=true;
int num6 = Convert.ToInt32(a);//1           

注意事项:

1)进行强制数据类型转换时可能会损失精度

2)一般情况下当一个算术表达式中有一"大"一"小"两种数据类型的数字进行运算时,整个表达式就是"大"的数据类型,相当于提升了表达式的级别

1) 损失精度
float a=3.9f;
//不会进行四舍五入
int b = (int)a;//3
2)提升表达式级别
示例:计算半径为 3 圆的面积
int r=3;
float PI=3.14f;
double s=PI * r * r;
计算过程:
PI*r时先将r提升至float,再与PI进行运算
PI*r*r 将最后的r提升至float,再与PI*r的值进行运算
最后赋值给s时又进行了隐式转换           
C#-类型转换,is或as进行类型转换及区别,null值,可空值类型 083

最终提升了表达式的级别

类的类型转换

类的类型转换也分为隐式(自动)与强制(显示)类型转换

//两者存在"父子"的继承关系
Student s = new Student(); 
Person p =s;//将子类对象隐式类型转换为父类对象
Student stu = (Student)p;//将父类对象强制类型转换为子类           
C#-类型转换,is或as进行类型转换及区别,null值,可空值类型 083

类的继承关系示意图

//=以下可以进行类型转换============
  //进行了隐式类型转换,子类赋值给父类对象
  Person p1 = new ZZ();//郑州
  //进行了强制类型转换,父类变量赋值给子类对象
  ZZ z1 = (ZZ)p1;
  //=以下不存在强制类型转换==========
  Chinese p2 = new Chinese();
  ZZ z2 = (ZZ)p2;
p2存储的是 Chinese的对象不是ZZ的对象,其它的以此类推           

is与as

1 使用 is 进行类型转换

class Person
{
    public string Name = "张三";
}
class Chinese : Person
{   }
//===============
 static void Main(string[] args)
 {
     //使用is进行转换,需要多进行一次判断           
     Person p1 = new Chinese();
     //先进行类型判断
     if (p1 is Chinese)
     {
         Chinese ch1 = (Chinese)p1;
         Console.WriteLine(ch1.Name);
     }
     else
     {
         //如果Person p = new Person();  
         //就会打印"类型不匹配"
         Console.WriteLine("类型不匹配");
     }
     Person p2 = new Person();
    //会报错
     Chinese ch2 = (Chinese)p2;
     Console.WriteLine(ch2.Name);
     Console.ReadKey();
 }           
C#-类型转换,is或as进行类型转换及区别,null值,可空值类型 083

使用is没有进行判断

2 使用 as 进行类型转换

Person p2 = new Person();
 //Chinese ch2 = (Chinese)p2;//会报错
 //如果转换成功返回转换成功后的类型(本示例是 Chinese)
 //如果转换失败返回null
 //因为p2声明时是 Person 所以 ch2 为 null
 Chinese ch2 = p2 as Chinese;
 //因此在使用 ch2 首先判断 ch2 不是null(空对象)
 if (ch2 != null)
 {
     Console.WriteLine(ch2.Name);
 }
 else
 {
     Console.WriteLine("ch2 为空对象,所以无法使用ch2.Name,使用就抛异常");
 }
//没有判断空对象,直接使用会抛异常
 Console.WriteLine(ch2.Name);           
C#-类型转换,is或as进行类型转换及区别,null值,可空值类型 083

使用as进行类型转换

使用is或as的区别

1)is只做类型的兼容性判断,并不进行类型转换,返回值为true或false,不会返回null,即使对象为null也会返回false

2)as在转换的同时兼判断兼容性,如果无法进行转换则 as 返回 null(没有产生新的对象)而不是引发异常;有了AS我想以后就不要再用try-catch来做类型转换的判断了,因此as转换成功要判断是否为null

3)使用as的效率要比is的高,因为使用is进行类型转换需要进行两次类型兼容检查,而as只需要做一次类型兼容,一次null检查,null检查要比类型兼容检查快

null值

只有引用类型(已说过的如object,字符串,数组,类,接口)的变量才有null值(表示不存在)

C#-类型转换,is或as进行类型转换及区别,null值,可空值类型 083

空指针异常, 空对象 未将对象引用到实例 意思一样

原因在于没有在内存堆中开辟相应的空间(new的作用之一),也就无法将对象p指向内存堆中应该开辟空间的地址(指向问题在之前的值与引用类型中说过)

还可以点出类的成员变量的原因在于VS工具根据对应的程序集的反射机制得以给出提示

可空的值类型:使用 ?(单问号)用于对 int,double,bool等无法直接赋值为 null 的数据类型进行 null 的赋值,简单来说就是这个数据类型是Nullable 类型的

表示其基础值类型正常范围内的值,再加上一个 null 值,在连接MSSQL数据库进行添加,修改操作时会用到,到时再说

//类的成员变量 a
int a; //如果不赋值默认为0
int? b;//如果赋值,可以赋int类型的值
//如果不赋值 默认值就会为 null           

继续阅读