[CLR via C#]8. 方法
一、实例构造器和类(引用类型)
类实例构造器是允许将类型的实例初始化为良好状态的一种特殊的方法。
类实例构造器方法在"方法定义元数据表"中始终叫.ctor(代表constructor)。创建一个引用类型的实例时,首先为实例的数据字段分配内存,然后初始化对象的附加字段(类型对象指针和同步块索引),最后调用类型的实例构造器来设置对象的初始化状态。
public class SomeType {
}
它等下于以下的代码:
piblic class SomeType {
    public SomeType () : base () { }
}
如果类的修饰符是abstract,那么编译器生成的默认构造函数的可访问性就是protected;否则,构造器就被赋予public可访问性。
如果基类没有提供默认的无参构造函数,那么派生类必须显示调用一个基类构造器,否则编译器会报错。
如果类的修饰符为static,那么编译器根本不会再类的定义中生成默认的实例构造器。
Internal sealed class SomeType {
    private Int32 m_x =;
}


internal sealed class SomeType {
        private Int32 m_x = ;
        private String m_s = "Hi there";
        private Double m_d = 3.14159;
        private Byte m_b;
        // Here are some constructors.
        public SomeType() { /* ... */ }
        public SomeType(Int32 x) { /* ... */ }
        public SomeType(String s) { /* ...; */ m_d = ; }
    }








internal sealed class SomeType
{
// 不显示初始化下面的字段
private Int32 m_x;
private String m_s;
private Double m_d;
private Byte m_b; // 该构造器将所有的字段都设为默认值
// 其它所有构造器显式调用这个构造器
public SomeType()
{
m_x = ;
m_s = "Hi there";
m_d = 3.14159;
m_b = 0xff;
} // 该构造器将所有的字段都设为默认值,然后修改m_x
public SomeType(Int32 x)
: this()
{
m_x = x;
} // 该构造器将所有的字段都设为默认值,然后修改m_x
public SomeType(String s)
: this()
{
m_s = s;
} // 该构造器将所有的字段都设为默认值,然后修改m_x和m_s
public SomeType(Int32 x, String s)
: this()
{
m_x = x;
m_s = s;
}
}
二、实例构造器和结构(值类型)
值类型(struct)构造器的工作方式与引用类型(class)的构造器截然不同。CLR总是允许创建值类型的实例,并且没有办法阻止值类型的实例化。所以,值类型其实并不需要定义构造器,C#编译器根本不会为值类型生成默认的无参构造器。如以下代码:
internal struct Point{
    pblic Int32 m_x, m_y;
}
internal sealed class Rectangle {
    public Point m_topLeft, m_bottomRight;
}
为了构造一个类Rectangle,必须使用new操作符,而且必须指定一个构造器。在这个例子中,调用的是C#自动生成的默认实例构造器,为Rectangle 分配内存时,内存中包含Point值类型的两个实例。处于对性能的考虑,CLR不会为包含在引用类型中的每个值类型字段都调用一个构造器。但是,如前面提到的,值类型的字段会被初始化为0或null。
internal struct Point {
    // 在C#中,向一个值类型应用关键字new,
    // 可以调用构造器来初始化值类型的字段。
    public Int32 m_x, m_y;
    public Point(Inte32 x, Int32 y) {
        m_x = x;
        m_y = y;
    }
} 
internal sealed class Rectangle {
    public Point m_topLeft, m_bottomRight;
    public Rectangle() {
        m_topLeft = new Point (, );
        m_bottomRight = new Point (, );
    }
}
好了,让我们来改变下上面的没有定义默认的无参构造器。
internal struct Point {
    public Int32 m_x, m_y;
    public Point() {
        m_x =m_y = ;
    }
} 
internal sealed class Rectangle {
    public Point m_topLeft, m_bottomRight;
    public Rectangle() {
    }
}
现在我们来想象,m_x和m_y值是多少呢?是5吗?还是0?
internal struct SomeValType {
    //不能再值类型中内联实例字段的初始化
    private Int32 m_x = ;
}    
internal struct SomeValType {
    private Int32 m_x,m_y;
    //C#允许为值类型定义有参构造器
    public SomeValType(Int32 x){
        m_x = x;
    }
}
//C#允许为之类定义有参构造器
public SomeValType(Int32 x){
//this代表本身实例,使用new操作符会将所有的字段初始化为0/null
this = new SomeValType();
//使用x覆盖m_x的0
m_x = x;
//现在y已经初始化为0了
}
注意,在引用类型的构造器中,this被认为是只读的,所以不能对它赋值。
三、类型构造器
除了实例构造器,CLR还支持类型构造器(type constructor),也称为静态构造器(static constructor)、类构造器(class constructor)等。
internal sealed class SomeRefType {
    static SomeRefType () {
        //SomeRefType 被首次访问时,执行这里的代码。
    }
}
internal struct SomeValType {
    //C#允许值类型定义无参构造器
    static SomeValType () {
        //SomeValType 被首次访问时,执行这里的代码。
    }
}
类型构造器总是私有的,C#编译器会自动把它们标记成private。之所以私有,是为了阻止任何有开发人员写的代码调用它,对它的调用总是由CLR负责的。
internal sealed class SomeType{
    public static Int32 s_x = ;
}
虽然C#不允许值类型为它的实例字段使用内联字段初始化语法,但可以为静态字段使用。
public sealed class TypeConstructorPerformance {
    public static void Go() {
        const Int32 iterations =  *  * ;
        PerfTest1(iterations);
        PerfTest2(iterations);
    }
    // 由于这个类没有显示定义类型构造器,所以C#在元数据中
    // 用BeforeFieldInit来标记类型定义
    internal sealed class BeforeFieldInit {
        public static Int32 s_x = ;
    }
    // 由于这个类显示定义了类型构造器,所以C#在元数据中
    // 没有用BeforeFieldInit来标记类型定义
    internal sealed class Precise {
        public static Int32 s_x;
        static Precise() { s_x = ; }
    }
    // 这个方法被JIT编译时, BeforeFieldInit 和Precise 类
    // 的类型构造器还没有被执行,所以这些构造器的调用将嵌入
    // 这个方法的代码中,使它允许较慢
    private static void PerfTest1(Int32 iterations) {
        Stopwatch sw = Stopwatch.StartNew();
        for (Int32 x = ; x < iterations; x++) {
            // JIT编译器优化调用BeforeFieldInit 的
            // 类型构造器的代码,是他在循环开始之前执行
            BeforeFieldInit.s_x = ;
        }
        Console.WriteLine("PerfTest1: {0} BeforeFieldInit", sw.Elapsed);
        sw = Stopwatch.StartNew();
        for (Int32 x = ; x < iterations; x++) {
            // JIT编译器在这里生成调用Precise 类的类型构造器的代码
            // 所以每次循环迭代,它都要核实一遍是否需要调用构造器
            Precise.s_x = ;
        }
        Console.WriteLine("PerfTest1: {0} Precise", sw.Elapsed);
    }
    // 这个方法被JIT编译时, BeforeFieldInit 和Precise 类的
    // 类型构造器已经执行过了。所以,在这个方法的代码中,不会
    // 在对这些构造器的调用,是它运行得更快
    private static void PerfTest2(Int32 iterations) {
        Stopwatch sw = Stopwatch.StartNew();
        for (Int32 x = ; x < iterations; x++) {
            BeforeFieldInit.s_x = ;
        }
        Console.WriteLine("PerfTest2: {0} BeforeFieldInit", sw.Elapsed);
        sw = Stopwatch.StartNew();
        for (Int32 x = ; x < iterations; x++) {
            Precise.s_x = ;
        }
        Console.WriteLine("PerfTest2: {0} Precise", sw.Elapsed);
    }
}


[CLR via C#]8. 方法的更多相关文章
- MSSQLSERVER添加c# clr程序集的使用方法
		
前言 MSSQLSERVER提供程序集,无疑可以让编程人员更加便捷的操作数据库数据,比如c#写的函数,可以在数据库当作sql的函数使用,你想想他对不熟悉数据库的程序员来说是有多么的嗨.这么好的机制,大 ...
 - 【Clr in c#】方法
		
1. 引用类型(class)与值类型(strust)的构造函数(实例构造器) 1, 创建一个引用类型的实例时,首先为实例的数据字段分配内存,然后初始对象的附加字段,最后调用实例构造器来设置对象的初始 ...
 - CLR如何调用虚方法、属性和事件
		
方法代表在类型或类型的实例上执行某些操作的代码.在类型上执行操作,称为静态方法:在类型的实例上执行操作,称为非静态方法.任何方法都有一个名称.一个签名和一个返回值(可以是void). CLR允许一个类 ...
 - CLR类型设计之方法与构造器
		
无论学习那门语言都要学习函数体,C#,JAVA,PHP,都会涉及到函数体,而C#的函数体成员并不少,方法和构造器就是函数体成员之一,函数体成员还包括但不限于:方法,属性,构造器,终结器,运算符及索引器 ...
 - 重温CLR(六)方法和参数
		
实例构造器和类(引用类型) 构造器是将类型的实例初始化为良好状态的特殊方法.构造器方法在“方法定义元数据表”中始终叫做.ctor(constructor的简称).创建引用类型的实例时,首先为实例的数据 ...
 - <NET CLR via c# 第4版>笔记 第8章 方法
		
8.1 实例构造器和类(引用类型) 构造引用类型的对象时,在调用类型的实例构造器之前,为对象分配的内存总是先被归零 .没有被构造器显式重写的所有字段都保证获得 0 或 null 值. 构造器不能被继承 ...
 - ASP.NET Core 中文文档 第二章 指南(4.10)检查自动生成的Detail方法和Delete方法
		
原文 Examining the Details and Delete methods 作者 Rick Anderson 翻译 谢炀(Kiler) 校对 许登洋(Seay).姚阿勇(Mr.Yao) 打 ...
 - CLR via C# 摘要一:托管程序的执行模型
		
托管程序的执行模型大致如下: 编译源代码为程序集(dll或exe文件),程序集包括了记录相关信息的元数据和IL代码 执行程序集文件时,启动CLR,JIT负责把IL编译为本地代码并执行 IL是微软推出的 ...
 - Clr Via C#读书笔记---垃圾回收机制
		
#1 垃圾回收平台的基本工作原理: 访问一个资源所需的具体步骤: 1)调用IL指令newobj,为代表资源的类型分配内存.在C#中使用new操作符,编译器就会自动生成该指令.2)初始化内存,设置资源的 ...
 
随机推荐
- php 方便快捷导出excel
			
/** * 导出excel * @param array $column * eg: $column = [ * 'username' => '姓名', * 'age' => '年龄', ...
 - Hadoop 2.7.1 源代码目录结构分析
			
采用的源代码是2.7.1的,从这个网站下可以找到2.7.1的代码:https://git1-us-west.apache.org/ ,使用gitclone出来,然后git checkout到2.7.1 ...
 - spring之ControllerAdvice注解
			
@ControllerAdvice是Spring 3.2新增的注解,主要是用来Controller的一些公共的需求的低侵入性增强提供辅助,作用于@RequestMapping标注的方法上. Contr ...
 - Apache+PHP+Mysql 集成环境   几个软件pk
			
WampServer 2.5 64位 - 工具软件 - 源码之家 2014年8月25日 - WampServer是Apache+PHP+Mysql 集成环境,拥有简单的图形和菜单安装和配置环境.支持2 ...
 - iOS7新JavaScriptCore框架入门介绍
			
前阵子,Apple正式发布了新的iOS 7系统,最大最直观的改变在于界面变得小清新范了,我也提到<iOS,你真的越来越像Android了>.不过对于移动开发者来说,除了要适应Xcode 5 ...
 - bootstrap fileinput 文件上传工具
			
这是我上传的第二个plugin 首先第一点就是因为这个好看 符合bootstrap的界面风格 第二是可以拖拽(虽然我不常用这个功能 但是这样界面看起来就丰满了很多) 最后不得不吐槽这个的回发事件 我百 ...
 - Mac终端常用命令收集
			
删除非空目录 rm -rf 目录名字 -r 就是向下递归,不管有多少级目录,一并删除-f 就是直接强行删除,不作任何提示的意思 终端修改hosts文件 sudo vi /etc/hosts 切换到su ...
 - 使用Spring MVC统一异常处理
			
http://blog.csdn.net/ufo2910628/article/details/40399539
 - location.hash属性介绍
			
location.hash属性介绍 例如URL: http://wwww.a.com/index#rhythmk 通过location.hash 我们将获取到 #rhythmk. 默认浏览器会滚动至i ...
 - xcode6.0  模拟器打不开
			
只要设置下这个就行了 本来以为虚拟机的问题 都把虚拟机从新安装了 杯具啊