注:书本第8章:方法

实例构造器和类(引用类型)

构造器方法在“方法定义元数据表”中始终叫做.ctor(constructor的简称)。

构造引用类型的对象,在调用类型的实例构造器之前,为对象分配的内存总是先被归零。

如果类没有显示定义任何构造器,c#编译器将定义一个默认(无参)构造器。如果类的修饰符为abstrat,那么编译器生成的默认构造器的可访问性就为protected;否则,构造器会被赋予public可访问性。静态类编译器根本不会生成默认构造器。

类的实例构造器在访问从基类继承的任何字段之前,必须先调用基类的构造器。

Obect的MemberwiseClone方法可以在不调用实例构造器的前提下创建类型的实例。

“内联”初始化,编译器会转换成调用构造器方法中的代码来执行。这样会容易使代码膨胀。

实例构造器和结构(值类型)

值类型其实并不需要定义构造器,c#编译器根本不会为值类型内联(嵌入)默认的无参构造器。

考虑到性能,CLR不会为包含在引用类型中的每个值类型字段都主动调用构造器。但是,值类型的字段会被初始化为0或null。

CLR确实允许为值类型定义构造器,但是必须显示调用才会执行。如下例子:

internal struct Point{
public Int32 m_x,m_y;
public Point(Int32 x,Int32 y){
m_x=x;
m_y=y;
}
}
internal sealed class Rectangle{
public Point m_topLeft,m_bottomRight; public Rectangle(){
//在C#中,向一值类型应用关键字new,
//可以调用构造器来初始化值类型的字段
m_topLeft=new Point(1,2);
m_bottomRight=new Point(100,200);
}
}

C#编译器不允许值类型定义无参构造器;但是CLR允许。所以C#不能在值类型中内联初始化字段。但是可以为静态字段进行内联初始化。

在值类型的构造器中,this代表值类型本身的一个实例,用new创建的值类型的一个实例可以赋给this。而在引用类型的构造器中,this被认为是只读的,所以不能对它进行赋值。

类型构造器(静态构造器、类构造器)

类型构造器方法总是叫.cctor。

类型默认没有定义类型构造器。如果定义,也只能定义一个。此外,类型构造器永远没有参数。c#自动将类构造器标记为private。不允许出现修饰符。

类型构造器只会被执行一次。

值类型可以定义类型构造器(但如前所述,不能定义无参实例构造器),但永远不会被执行。

类型只有在AppDomain卸载时才会卸载。AppDomain卸载时,用于标识类型的对象(类型对象)将成为“不可达”的对象(不存在对它的引用),垃圾回收器会回收类型对象的内存。

CLR不支持静态Finalize方法。可以在System.AppDomain类型的DomainUnload事件登记一个回调方法。

操作符重载方法

CLR规范要求操作符重载方法必须是public和static方法。要求操作符重载方法至少有一个参数的类型与当前定义这个方法的类型相同,以便C#编译器能在合理的时间内找到要绑定的操作符方法。

public sealed class Complex{
public static Complex operator+(Complex c1,Complex c2){ }
}

 编译器为名为op_Addition的方法生成元数据方法定义项;这个方法还设置了specialname标志,表明这是一个“特殊”方法。

转换操作符方法

将对象从一个类型转换为另一种类型的方法。CLR规范要求转换操作符重载方法必须是public和static方法。

一般的非基元类型,在执行强行转型时,CLR只是检查对象的类型和目标类型(或者从目标类型派生的其他类型)是不是相同。

public sealed class Rational{
//由一个Int32构造一个Rational
  public Rational (Int32 num){ ... }   //由一个Single构造一个Rational
  public Rational(Single num){ ... }
  //将一个Rational转换成一个Int32
  public Single ToString(){ ... }     //由一个Int32隐式构造并返回一个Rational  
  public static implicit operator Rational(Int32 num){
    return
new Rational(num);
  }
  //由一个Single隐式构造并返回一个Rational
  public static implicit operator Rational(Single num){
    return new Rational(num);
  }
  //由一个Rational显式返回一个Int32
  public static explicit operator Int32(Rational r){
    return r.ToInt32();
  }
  
  //由一个Rational显示返回一个Single
  public static explicit operator Single(Rational r){
    return r.ToSingle();
  }
}

在C#中,impicit关键字告诉编译器为了生成代码来调用方法,不需要在源代码中进行显示转型,expicit只有发现了显示转型,才调用方法。

只有在转换不损失精度或数据级的前提下(比如将个Int32转换成Rational)才能定义隐式转换操作符。如果有,应该定义一个显式转换操作符。

使用强制类型转换表达式时,C#生成代码调用显式转换操作符方法。使用as或is操作符时,则永远不会调用这些方法。

扩展方法

它允许定义一个静态方式,并用实例方法的语法来调用。要将方法变成扩展方法,只需在第一个参数前加this关键字:

public static class StringBuilderExtensions{
  public static Int32 IndexOf(this StringBuilder sb,Char value){//假定StringBuilder中没有IndexOf方法
    for(Int32 index=0;index<sb.Length;index++)
      if(sb[index]==value)return index;
    return -1;
  }
}
Int32 index=sb.IndexOf('X');

 C#只支持扩展方法,不支持扩展事件、属性、操作符等。

分部方法

//工具生成的代码,存储在某个源代码文件中
internal sealed partial class Base{
  private String m_name;
  //这是分部方法的声明
  partial void OnNameChanging(string value);
  
  public String Name{
    get{ return m_name; }
    set{
      OnNameChanging(value.ToUpper());//通知类要进行更改了
      m_name=value;//更改字段
    }
  }
} //开发人员生成的代码,存储在另一个源代码文件中:
internal sealed partial class Base{
  //这是分部方法的实现,会在m_name更改前调用
  partial void OnNameChanging(String value){
    if(String.IsNullOrEmpty(value))
      throw new ArgumentNullException("value");
  }
}

 分部方法只能在分部类或结构中声明;

分部方法的返回类型始终是void,任何参数都不能用out修饰符来标记。

 分部方法总是被视为private方法,但是c#编译器禁止在分部方法声明之前添加private关键字。

CLR via c#读书笔记五:方法的更多相关文章

  1. clr via c#读书笔记五:常量和字段

    1.常量是值从不变化的符号.只能定义编译器识别的基元类型的常量.如:Boolean,Char,Byte,SByte,Int16,UInt16,Int32,UInt32,Int64,Single,Dou ...

  2. [Clr via C#读书笔记]Cp8方法

    Cp8方法 构造器 作用就是初始化所有成员字段:.ctor:派生类和基类都有自己的构造函数.默认有一个无参数的构造函数,值字段初始化为0,引用字段初始化为null:可以有多个构造器: 值类型的初始化其 ...

  3. CLR via C# 读书笔记---常量、字段、方法和参数

    常量 常量是值从不变化的符号.定义常量符号时,它的值必须能在编译时确定.确定后,编译器将唱两只保存在程序集元数据中.使用const关键字声明常量.由于常量值从不变化,所以常量总是被视为类型定义的一部分 ...

  4. 《CLR.via.C#第三版》第二部分第10,11章节读书笔记(五)

    第10章是对 属性 做阐述 属性本质上是方法 匿名类型的使用: }; Console.WriteLine("Name={0},Year={1}",o1.Name,o1.Year); ...

  5. CLR via C# 读书笔记-26.线程基础

    前言 这俩个月没怎么写文章做记录分享,一直在忙项目上线的事情,但是学习这件事情,停下来就感觉难受,clr线程这章也是反复看了好多遍,书读百遍其义自见,今天我们来聊下线程基础 1.进程是什么,以及线程起 ...

  6. CLR via C# 读书笔记-27.计算限制的异步操作(上篇)

    前言 学习这件事情是一个习惯,不能停...另外这篇已经看过两个月过去,但觉得有些事情不总结跟没做没啥区别,遂记下此文 1.CLR线程池基础 2.ThreadPool的简单使用练习 3.执行上下文 4. ...

  7. CLR via C# 读书笔记-21.托管堆和垃圾回收

    前言 近段时间工作需要用到了这块知识,遂加急补了一下基础,CLR中这一章节反复看了好多遍,得知一二,便记录下来,给自己做一个学习记录,也希望不对地方能够得到补充指点. 1,.托管代码和非托管代码的区别 ...

  8. Effective Java 读书笔记之六 方法

    一.检查参数的有效性 1.考虑参数有哪些限制,把限制写到文档中,在方法的开头处通过显式地检查来实施这些限制. 二.必要时进行保护性拷贝 1.如果类具有从客户端得到或者返回的可变组件,类就必须考虑保护性 ...

  9. Clr Via C#读书笔记---I/O限制的异步操作

    widows如何执行I/O操作      构造调用一个FileStream对象打开一个磁盘文件-----FileStream.Read方法从文件中读取数据(此时线程从托管代码转为本地/用户模式代码)- ...

随机推荐

  1. springMVC框架下返回json格式的对象,list,map

    原文地址:http://liuzidong.iteye.com/blog/1069343 注意这个例子要使用jQuery,但是jquery文件属于静态的资源文件,所以要在springMVC中设置静态资 ...

  2. 【[SCOI2008]奖励关】

    又抄了一篇题解 要凉了要凉了,开学了我还什么都不会 文化课凉凉,NOIP还要面临爆零退役的历史进程 这道题挺神的,期望+状态压缩 我们设\(dp[i][S]\)表示在第\(i\)天前,捡的宝物状态为\ ...

  3. Java中int和String的转换问题

    int -> String int i=12345;String s="";第一种方法:s=i+"";第二种方法:s=String.valueOf(i); ...

  4. Nodejs与mysql连接池的应用(pool)

    /* * 连接池 连接和缓存的技术 * */ var mysql = require('mysql'); var pool = mysql.createPool({ connectionLimit:2 ...

  5. Python书单

    gitbook.jb51 1.Python基础教程 2.流畅的Python:总有论坛的人吐槽它翻译的还是不太友好,其实真正的差别没有那么大,重要的还是有所收获 3.<Python进阶>译本 ...

  6. Struts2+hibernate 结合,实现登陆校验

    完整的项目在github中,数据库使用postgresql,建表语句见项目文档. 下面我分块介绍一下struts2.hibernate.与页面部分的代码. Struts2 UserAction.jav ...

  7. oracle sqldrl命令与以及ctl文件

    具体操作如下: 第一步:先编辑好数据控制文件 xx.ctl,如test.ctl options(skip=1)   --跳过第一行(看实际情况) load data infile 'C:\Users\ ...

  8. Oracle子查询之高级子查询

    Oracle 高级子查询 高级子查询相对于简单子查询来说,返回的数据行不再是一列,而是多列数据. 1,多列子查询 主查询与子查询返回的多个列进行比较 查询与141号或174号员工的manager_id ...

  9. 【Django笔记一】windows系统下搭建Django项目

    一.环境版本信息: 操作系统:windows10 Django版本:2.0.5 Python版本:3.6.4 二.创建虚拟环境: 1.为什么要创建虚拟环境: 我们要开发一个新的项目,需要一套独立的Py ...

  10. chromium之message_pump_default

    看看头文件,默认的消息泵,该类实现了MessagePump的四个接口 class MessagePumpDefault : public MessagePump { public: MessagePu ...