对象初始化器
对象任何可以访问的字段/属性在构建之后,可通过对象初始化器直接为其进行设定值
public class Bunny{public string Name;public bool LikesCarrots;public bool LikesHumans;public Bunny(){ }public Bunny(string n) { Name = n; }}public class Test{public static void Main(){Bunny b1 = new Bunny { Name = "bo" };Bunny b2 = new Bunny("bo") { LikesCarrots = true, LikesHumans = false };}}
对象初始化器 VS 可选参数
如果不使用初始化器,上例中的构造函数也可以使用可选参数:
public class Bunny{public string Name;public bool LikesCarrots;public bool LikesHumans;public Bunny(string n, bool likesCarrots = false, bool likesHumans = false){Name = n;LikesCarrots = likesCarrots;LikesHumans = likesHumans;}}public class Test{public static void Main(){Bunny b2 = new Bunny(n: "Bo", likesCarrots: false);}}
可选参数方法
优点:可以让Bunny类的字段/属性只读
缺点:每个可选参数的值都被嵌入到了Calling site,C#会把构造函数的调用翻译成:
Bunny b2 = new Bunny("Bo", false);
THIS 引用
this引用指的是实例的本身
public class Panda{public Panda Mate;public void Marry(Panda partner){Mate = partner;partner.Mate = this;}}
this引用可以让你把字段与本地变量或参数区分开
只有class/struct的非静态成员菜可以使用this
public class test{string name;public test(string name){this.name = name;}}
属性 PROPERTYIES
从外面来看,属性和字段很像。但从内部看,属性含义逻辑,就像方法一样
Stock stock = new Stock();public void Main(){stock.CurremtPrice = 30; //使用起来和字段没有什么区别stock.CurremtPrice = -3;}
属性的声明
属性的声明和字段的声明很像,但多了一个get set块
public class Stock{decimal curremtPrice;public decimal CurremtPrice{get{return curremtPrice;}set{curremtPrice = value;}}}
属性的GET SET
get/set代表属性额访问器
get访问器会在属性被读取的时候运行,必须返回一个该属性类型的值
set访问器会把属性被赋值的时候运行,有一个隐式的该类型的参数value,通常你会把value付给一个私有字段 例子
属性与字段的区别
尽管属性的访问方式与字段的访问方式相同,但不同之处在于,属性赋予了实现者对获取和赋值的完全控制权。这种控制允许实现者选择任意所需的内部表示,不同属性的使用者公开其内部实现细节。
只读和计算的属性
如果属性只有get就是只读反之只写。
幕后字段value
EXPRESSION-BODIED 属性
从C#6开始,你可以使用Expression-bodied形式来表示只读属性
public decimal Worth => currentPrice * sharesOwned;//C#7,允许set访问器也可以使用该形式public decimal Worth{get => currentPrice * sharesOwned;set => sharesOwned = value / currentPrice;}//其本质上还是和之前一样,只是写法改变相当于语法糖,编译器编译的时候还是会自动携程之前那样的形式。
自动属性
属性最常见的一种实践就是:getter和setter只是对private field进行简单直接的读写
自动属性声明就是告诉编译器来提供这种实现
public decimal Worth { get; set; }
原理同上
编译器会自动生成一个私有的幕后字段,其名称不可引用(由编译器生成)
set访问器也可以是private或protected
属性初始化器
从C#6开始,你可以为自动属性添加属性初始化器
public decimal Worth { get; set; } = 123m;
只读同理。(只读自动属性也可以在构造函数里被赋值)
也可以对访问器设置访问级别private..
索引器
索引器提供了一种可以访问封装了列表值或字典值的class/struct的元素的一种自然的语法。
string s = "Hello";System.Console.WriteLine(s[0]);
语法很像使用数组时用的语法,但是这里的索引参数可以使任何类型的
索引器和属性拥有同样的修饰符
可以按照下列方式使用null条件操作符
string s = null;System.Console.WriteLine(s?[0]);
实现索引器
需要定义一个this属性,并通过中括号指定参数。
class syq{public string[] Str = "Hello World!".Split();public string this[int index]{get { return Str[index]; }set { Str[index] = value; }}}
使用的话,类似于数组
多个索引器
一个类型可以声明多个索引器,他们的参数类型可以不同
一个索引器可以有多个参数
public string this[int index, string strIndex]{get { ...; }set { ...; }}
只读索引器
如果不写set访问器,俺么这个索引器就是只读的。
在C#6以后,也可以使用Expression-bodied语法
public string this[int index] => Str[index];
CLR索引器的实现
索引器在内部会编译成get_Item或set_Item方法
public string get_Item(int wordNum){..}public string set_Item(int wordNum,string value){..}
