编程结构(C#)

正文

值类型和引用类型

值类型派生自System.ValueType,分配在栈上,不能被继承,变量默认按值传递,当它们超出定义的作用域时被回收。

引用类型分配在托管堆上,变量指向实例所占的内存地址,变量默认按引用传递(变量的地址传入被调用的函数),托管堆被垃圾回收时变量消亡。

 

传值与传址

按值传递值类型,被调用者不能改变参数值;按引用传递值类型,可以改变参数值。

如果按值传递引用类型,被调用者可能改变对象的状态数据的值,但不能改变所引用的对象,即不能让对象指向另外一个对象。

如果按引用传递引用类型,被调用者可能改变对象的状态数据的值和所引用的对象。

 

参数修饰符out和ref的区别

out: 调用方法之前不需要初始化,输出参数由被调用的方法赋值,如果被调用的方法没给输出参数赋值,会出现编译错误。

ref: 调用者赋初值,并且可以由被调用方法(可选地)重新赋值。

 

Internal和protected作用范围

Internal: 只能在包含它的程序集中访问该方法

Protected: 只有派生的类型和该类本身能访问该方法。

Protected internal: 只能在包含它的程序集,和派生类的代码中访问。

 

Using关键字

Using关键字用来:确保在对象引用超出作用域时,在实现了IDisposable接口的对象上自动调用Dispose()方法,实现资源回收。

静态构造函数

静态构造函数适用于初始化在编译时未知的静态数据值,例如,需要从外部文件/数据库读取或生成随机数等。一个类只能定义一个静态构造函数,静态构造函数只执行一次,静态构造函数的执行优先于任何实例级别的构造函数。

垃圾回收

在使用.NET进行托管编程时,不需要对托管堆进行直接操作。如果托管堆没有足够的内存来分配请求的对象,GC就会进行垃圾回收。

重写Finialize()的唯一原因是,C#类通过PInvoke或COM互操作性使用了非托管资源(如原始的操作系统文件句柄,数据库连接等)。

Finialize方法是保证垃圾回收时清除非托管资源。但对于数据库和文件句柄等非常宝贵的资源,应该尽快释放。除了重写Finialize()方法之外,可以实现IDisposable接口,它定义的Dispose方法可以由用户手工调用。

 

对象的代

垃圾回收时,CLR会试图寻找不可到达的对象,它不会逐个检查托管堆上的每一个对象。为了优化这个过程,堆上的每一个对象都属于某个代:

第0代:从没有标记为回收的新分配的对象

第1代:在上一次垃圾回收中没有被回收的对象

第2代:在一次以上的垃圾回收后仍然没有被回收的对象

垃圾回收器检查和处理所有的第0代对象,如果获得足够的空闲内存,就不用继续检查第1代和第2代的对象,同时没有被回收的对象被提升到第1代。

 

GAC

Global Assembly Cache是全局程序集缓存。大多数共享程序集都安装在这个缓存中,其中也安装了一些私有程序集。如果私有程序集使用本机图像生成器(Ngen.exe)编译为本机代码,也会存储在这个缓存中。

内部图像生成器(native image generator)Ngen.exe,可以在安装期间把IL代码编译为本机代码,这样程序启动更快。

 

 

正式的处置模式

    public class MyResourceWrapper : IDisposable {

        private bool disposed = false;

 

        public void Dispose() {

            CleanUp(true);

            GC.SuppressFinalize(this);//跳过终结

        }

 

        private void CleanUp(bool disposing) {

            if (!this.disposed) {

                if (disposing) {

                    //释放托管的资源(在包含的可处置对象上调用Dispose)

                }

                //在这里释放非托管的资源

            }

            disposed = true;

        }

 

        ~MyResourceWrapper() {

            CleanUp(false);

        }

    }

猜你喜欢

转载自blog.csdn.net/Nicky_1218/article/details/85127987