CSharp Basic Tutorial Chapter-3-3 class 对象初始化 this 属性 索引器


对象初始化器

对象任何可访问的字段/属性在构建之后,可通过对象初始化器直接为其进行设定值
1

编译器生成的代码

2

对象初始化器 vs 可选参数

  • 如果不使用初始化器,上例中的构造函数也可以使用可选参数:

3

可选参数方式

  • 优点:可以让Bunny类的字段/属性只读
  • 缺点:每个可选参数的值都被嵌入到了calling site,C#会把构造函数的调用翻译成:
Bunny b1 = new Bunny("Bo",true,false);

This 引用

  • this引用指的是实例的本身。

4

  • this引用可以让你把字段与本地变量或参数区分开
  • 只有class/struct的非静态成员才可以使用this
public class Test
{
  string name;
  public Test(string name){ this.name=name;}
}

属性 Propertyies

  • 从外边来看,属性和字段很像。但从内部看,属性含有逻辑,就像方法一样

5

属性的声明

  • 属性的声明和字段的声明很像,但多了一个 get set 块。

6

属性的get set

  • get/set 代表属性的访问器
  • get访问器会在属性被读取的时候运行,必须返回一个该属性类型的值
  • set访问器会在属性被赋值的时候运行,有一个隐式的该类型的参数 value,通常你会把 value 赋给一个私有字段

属性与字段的区别

  • 尽管属性的访问方式与字段的访问方式相同,但不同之处在于,属性赋予了实现者对获取和赋值的完全控制权。这种控制允许实现者选择任意所需的内部表示,不向属性的使用者公开其内部实现细节。

只读和计算的属性

  • 如果属性只有get访问器,那么它是只读的
  • 如果只有set访问器,那么它就是只写的(很少这样用)
  • 属性通常拥有一个专用的“幕后”字段(backing field),这个幕后字段用来存储数据

7

Expression-bodied 属性

  • 从C# 6开始,你可以使用Expression-bodied形式来表示只读属性
    public decimal Worth => currentPrice * shareOwned

C# 7,允许set访问器也可以使用该形式

public decimal Worth
{
  get => currentPrice * shareOwned;
  set => sharesOwned = value/currentPrice;
}

自动属性

  • 属性最常见的一种实践就是:getter和setter只是对private field进行简单直接的读写
  • 自动属性声明就告诉编译器来提供这种实现
public class Stock
{
  ...
  public decimal CurrentPrice{get;set;}
}
  • 编译器会自动生成一个私有的幕后字段,其名称不可引用(由编译器生成)
  • set 访问器也可以是private 或 protected

属性初始化器

  • 从C# 6 开始,你可以为自动属性添加属性初始化器

    public decimal CurrentPrice{get;set;}= 123;
  • 只读的自动属性也可以使用(只读自动属性也可以在构造函数里被赋值)

    public int Maximun { get;}= 999;

get 和 set的访问性

  • get和set访问器可以拥有不同的访问级别
  • 典型用法:public get,internal/private set
  • 注意,属性的访问级别更“宽松”一些,访问器的访问级别更“严”一些

8

CLR的属性实现

  • C#的属性访问器内部会编译成 get_XXX 和 set_XXX
public decimal get_CurrentPrice{...}
public void set_CurrentPrice(decimal value){...}

简单的非virtual属性访问器会被JIT编译器进行内联(inline)操作,这会消除访问属性与访问字段之间的性能差异。内联是一种优化技术,它会把方法调用换成直接使用方法体。

索引器

  • 索引器提供了一种可以访问封装了列表值或字典值的class/struct的元素的一种自然的语法。

9

  • 语法很像使用数组时用的语法,但是这里的索引参数可以是任何类型的
  • 索引器和属性拥有同样的修饰符
  • 可以按照下列方式使用null条件操作符:

10

实现索引器

  • 需要定义一个this属性,并通过中括号指定参数。

11

使用索引器

12

多个索引器

  • 一个类型可以声明多个索引器,它们的参数类型可以不同
  • 一个索引器可以有多个参数

13

只读索引器

  • 如果不写set访问器,那么这个索引器就是只读的
  • 在C# 6以后,也可以使用 expression-bodied 语法
public string this [int wordNum] => words[wordNum]

CLR的索引器实现

  • 索引器在内部会编译成get_Item和set_Item方法
public string get_Item(int wordNum){...}
public void set_Item(int wordNum, string value){...}

文章作者: Chaoqiang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Chaoqiang !
评论
 上一篇
CSharp Basic Tutorial Chapter-3-4 常量  静态构造函数和类  终结器  局部类和方法 nameof CSharp Basic Tutorial Chapter-3-4 常量 静态构造函数和类 终结器 局部类和方法 nameof
常量 一个值不可以改变的静态字段 在编译时值就已经定下来了。 任何使用常量的地方,编译器都会把这个常量替换为它的值 常量的类型可以是内置的数值类型、bool、char、string或enum 使用const关键字声明,声明的同时必须使用具体
下一篇 
CSharp Basic Tutorial Chapter-3-2 构造函数和解析函数 CSharp Basic Tutorial Chapter-3-2 构造函数和解析函数
构造函数 在class或struct上运行初始化代码 和定义方法差不多,但构造函数的名和类型名一致,返回类型也和类型一致,并且返回类型就省略不写了 C#7,允许单语句的构造函数写成expression-bodied成员的形式 构造函数重
  目录