c# class

field

是class的成员,是一个成员

readonly修饰符

  • 防止字段在构造之后被改变
  • readonly字段只能在声明的时候被赋值,或在构造函数里被赋值

字段初始化

  • 字段可以初始化
  • 未初始化的字段有一个默认值
  • 字段的初始化在构造函数之前运行

overload

类型里的方法可以进行重载(允许多个同名的方法同时存在),只要这些方法的签名不同就行

void Foo (int x) {}
void Foo(double x) {}
void Foo(int x, double y) {}

构造函数

  • 运行class或struct的初始化代码
  • 和方法差不多,方法名和类型一致,返回类型也和类型一致,但不写了
  • C#7,允许单语句的构造函数写成expression-bodied成员的形式
public class Panda
{
  string name;
  public Panda(string n) => name = n;
}

构造函数的重载

  • class和struct可以重载构造函数
  • 调用重载函数时使用this
  • 当同一个类型下的构造函数A调用构造函数B的时候,B先执行
  • 可以把表达式传递给另一个构造函数,但表达式本身不能使用this引用,因为这时候对象还没有被初始化,所以对象上任何方法的调用都会失败。但是就可以时候用static 方法


    image.png
public class Wine 
{
    public decimal Price;
    public int Year;

    public Wine(decimal price)
  {
    Price = price;
  }
  public Wine(decimal price, int year) : this(price)
  {
    Year = year;
  }
}

public Wine (decimal price, DateTime date): this(price, Wine.GetYear()) 
{
  Date = date
}
public static int GetYear(){return 1998;}

构造函数和字段的初始化顺序

  • 字段的初始化发生在构造函数执行之前
  • 字段按照声明的前后顺序进行初始化

非pulic的构造函数

  • 构造函数可以不是public的
class Test 
{
  public static void Main(string[] args)
  {
    var wine = Wine.CreateInstance();
  }
}

public class Wine
{
  Wine(){}
  public static Wine CreateInstance(){
  return new Wine();
}

}

Deconstructor

  • 作用基本和构造函数相反,它会把字段反赋给一堆变量
  • 方法名必须是Deconstruct,有一个或者多个out参数
  • Deconstruct 可以被重载
class Rectangle 
{
  public readonly float Width, Height;
  public Rectangle(float width, float height){
    Width = width;
    Height = height;
  }
  public void Deconstruct(out float width, out float height){
    width = Width;
    height = Height;
  }  
}

class Test 
{
  public static void Main(string[] args){
  var rect = new Rectangle(3,4);
  //rect.Deconstruct(out var width, out var height);
  var (width, height) = rect;
  Console.WriteLine(width + " " + height); //3,4
  }
}
  • Deconstruct可以使用扩展方法
public static class Extension
{
  public static void Deconstruct(this Rectangle rect, out float width, out float height)
  {
     width = rect.Width;
     height = rect.Height;
  }
}

...
var rect = new Rectangle(3,4);
Extensions.Deconstruct(rect, out var width, out var height);
...

对象初始化器

  • 对象任何可访问的字段/属性在构建之后,可通过对象初始化器直接为其进行设定值
public class Bunny
{
  public string Name;
  public bool LikesCarrots;
  public bool LikesHumans;

  public Bunny () {}
  public Bunny(string n) {Name = n;}
}

...
Bunny b1 = new Bunny{ Name ="Bo, LikesCarrots = true, LikesHumans = false};
Bunny b2 = new Bunny("Bo") { LikesCarrots = true,  LikesHumans = false}

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

public Buuny(string name, bool likesCarrots = false, bool likesHumans = false)
{
  Name = name;
  LikesCarrots = likesCarrots;
  LikesHumans = likesHumans
}

可选参数方式

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

This 引用

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

属性 Property

  • 从外边来看,属性和字段很像。 但是从内部看,属性含有逻辑,就像方法一样
  • 属性的声明和字段很像,但是多了一个get set 块
public class Stock
{
  decimal currentPrice;
  public decimal CurrentPrice
  {
    get { return currentPrice;}
    set { currentPrice = value;}
  }
}

属性的get set

  • get/set 代表属性的访问器
  • get访问器会在属性被读取的时候运行,必须返回一个该属性类型的值
  • set访问器会在属性被赋值的时候运行,有一个隐式的该类型的参数value,通常你会把value赋给你个私有字段
  • 尽管属性的访问方式与字段的访问方式相同,但不同之处在于,属性赋予了实现者对获取和赋值完全控制权。这种控制允许实现者选择任意所需的内部表示,不向属性的使用者公开其内部实现细节

只读和计算的属性

  • 如果属性只有get访问器,那么它是只读的
  • 如果只有set访问器,那么它是只写的
  • 属性通常拥有一个专用的幕后字段,这个幕后字段用来存储数据

自动属性

  • 属性最常见的一种实践就是: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 Maxinum {get;} = 999;
  • get set访问器可有不同的访问级别, 典型用法,public get, internal/private set
public class Foo 
{
  private decimal x;
  public decimal x {
    get { return x;}
    private set {x = Math.Round(value, 2)}
  }

你可能感兴趣的:(c# class)