C# new关键字和对象类型转换(双括号、is操作符、as操作符)
一、new关键字
CLR要求所有的对象都通过new来创建,代码如下:
Object obj=new Object();
以下是new操作符做的事情
1、计算类型及其所有基类型(一直到System.Object,虽然它没有定义自己的实例字段)中定义的所有实例字段需要的字节数.堆上每个对象都需要一些额外的成员,包括“类型对象指针”和"同步索引块"。CLR利用这些成员管理对象.额外成员的字节数要计入对象的大小.
2、从托管堆中分配类型要求的字节数,从而分配对象的内存,分配的所有字节都设为0
3、初始化对象的"类型对象指针"和"同步索引块"成员
4、调用类型的实例构造器,传递在new调用中指定的实参,大多数编译器都在构造器中自动生成代码来调用基类构造器,每个类型的构造器都负责初始化该类型定义的实例字段.最终调用System.Object的构造器,该构造器什么都不做.
注:没有和new操作符对应的delete操作符,换言之,没有办法显示释放为对象分配的内存.CLR采用了垃圾回收机制,能自动检测到一个对象不在被使用或者访问,并自动释放对象的内存.
二、对象类型转换
1、基础知识
CLR最重要的特性之一就是类型安全.在运行时,CLR总能知道当前对象是什么类型,调用GetType方法即可知道当前对象是什么类型,由于GetTpye是非虚方法,所以一个类型不能伪装成另一个类型.例如Employee类型不能重写GetType方法来返回一个SuperHero类型.
但是,日常开发中,经常需要将一种类型转换成另一种类型,CLR允许将对象转换成其实际类型或者它的任何基类型.每种编程语言都规定了开发人员具体如何进行这种转换.C#不要求任何特殊语法即可将对象转换成它的基类型,因为向基类型转换被认为是一种类型安全的转换.
对象转换成基类型的代码如下:
public class Program { static void Main(string[] args) { //因为CLR中,Object是所有类型的基类,所以不需要转型 Object obj = new Person(); } } internal class Person { }
然而将一个对象转换成其派生类型(也就是子类型)时,C#要求进行显式的转换,因为这种转换可能会在运行时失败!
将对象转换成其派生类型(子类型),代码如下:
public class Program { static void Main(string[] args) { //因为CLR中,Object是所有类型的基类,所以不需要转型 Object obj = new Person(); //需要强制转换,因为Person派生自Object Person p = (Person)obj; } } internal class Person { }
注:进行强制转换的对象必须是接收类型的派生类型,如果不是,编译器会报System.InvalidCastException异常.
2、使用is和as来进行强制转换
(1)、is操作符
C#中进行类型转换的另一种方式是使用is操作符,is检查对象是否兼容于指定类型,返回boolean值true或者false,注意:is操作符永远不抛出异常,代码如下:
public class Program { static void Main(string[] args) { Object obj = new Object(); Console.WriteLine(obj is Person); Person p = new Person(); Console.WriteLine(p is Person); Console.ReadKey(); } } internal class Person { }
is操作符通常像下面这样使用:
if (stu is Person) { Person p = (Person)stu; }
在上述的代码中,CLR实际进行了两次的代码检查,is操作符首先核实stu是否兼容于Person类型,如果是,在if语句内部转型时,CLR再次核实stu是否引用一个Person类型,CLR的类型检查增强了安全性,但无疑会对性能造成一定的影响,应为CLR首先必须去判断变量引用的实际类型,用每个基类型去核对指定的类型.
2、as操作符
为了简化is操作符的做法,同时提供is操作符的性能,C#专门提供了as操作符,as操作符的工作方式与强制类型转换一样,只是它永远不抛出异常,如果对象不能转换,结果就是null.所以正确使用as操作符的做法是检查转型结果是否为null,如果直接使用这个结果可能会抛出System.NullReferenceException异常,代码如下:
public class Program { static void Main(string[] args) { Object obj = new Object(); Person p = obj as Person;//这个转换会失败,但是p会被设为null,不抛出异常 string exceptionInfo = p.ToString();//这里访问p会抛出异常 Console.WriteLine(exceptionInfo); Console.ReadKey(); } } internal class Person { }
相关文章
- [原创]C# 与 汇编 的一次亲密接触。
- C# Eval在aspx页面中的用法及作用
- C#异步编程一
- 《C#高级编程》学习笔记----c#内存管理--栈VS堆
- 《C#高级编程》学习笔记------C#中的委托和事件(续)
- C#基础视频教程6.1 如何简单读写数据库
- c#匿名类,匿名对象
- C# 中使用System.Net.Http.HttpClient 模拟登录博客园 (GET/POST)
- C#[Serializable]在C#中的作用-NET 中的对象序列化
- c# checked 和 unchecked
- mysql 在c# EF 中无法生成对象
- C# 将一个对象转换为指定类型
- C# 中的.pdb/ .vshost.exe/ .vshost.exe.manifest文件
- C#中三种定时器对象的比较
- C# DataGridView的列对象属性探讨 (未完待续)
- C# 格式化string类型的金额
- C# FTP上传下载(支持断点续传)
- C# 对象比较(值类型、引用类型)
- atitit.判断时间重叠方法总结 java c++ c#.net js php
- C#中数组、ArrayList与List对象的区别
- 猿创征文|C#基础——DBHelper
- c# 控制职能运行单一实例,再次运行显示已经运行的实例
- C# OpenFileDialog和PictrueBox
- C#串口通信类
- c#:Ocelot集成Consul初体验
- C# lambda表达式原理定义及实例详解
- C#比较两个对象是否为同一个对象。 Visual Studio调试器指南---多线程应用程序调试(一)
- [C#]c#中数据的同步加锁机制 的几种方法