• 第十五章、实现属性以访问字段


      属性既维持了封装性,又可以使用字段风格的语法。

      什么是属性

      属性是字段和方法的交集——看起来像字段,用起来像方法。访问属性所使用的语法和访问字段相同。然而,编译器会将这种风格的语法自动转换成对特定访问器方法的调用。属性的声明如下所示:

      访问修饰符 类型 属性名

      {

      get

      {

      //取值代码

      }

      set

      {

      //赋值代码

      }

      }

      属性可以包含两个代码块,分别以get和set关键字开头。其中,get块包含读取属性时执行的语句,set块包含向属性写入时执行的语句。属性的类型指定了由get和set访问器读取和写入的数据的类型。

      所有set访问器都用一个隐藏的、内建的参数(名为value)来传递要写入的数据。

      struct ScreenPosition{

      private int _x,_y;

      public ScreenPosition(int X,int Y)

      {

      this._x = rangeCheckedX(X);

      this._y = rangeCheckedY(Y);

      }

      public int X  //定义属性

      {

      get {return this._x;}

      set{this._x = rangeCheckedX(value);}

      }

      public int Y  //定义属性

      {

      get {return this._y;}

      set{this._y = rangeCheckedY(value);}

      }

      private static int rangeCheckedX(int x){.......}

      private static int rangeCheckedY(int y){.......}

      }

      属性唯一要求的就是由get访问器返回指定类型的值。值还能动态计算获得,不一定要从存储好的数据中获取。

      使用属性

      在表达式中使用属性时,要么取值,要么赋值。

      ScreenPosition origin = new  ScreenPosition(0,0);

      //取值,调用后get访问器

      int xpos = origin.X //实际调用origin.X.get

      int ypos = origin.Y //实际调用origin.Y.get

      //赋值,调用set访问器

      origin.X = 40;  //实际

           origin.X += 40; //同时取值和赋值,get和se调用origin.X.set , value = 40

      origin.Y = 100;  //实际调用origin.Y.set , value = 100t访问器都会被调用

      只读属性:可以声明只包含get访问器的属性,这称为只读属性。只读属性不包含set访问器,对其进行写入操作会报告编译错误。

      只写属性:类似的,可声明只包含set访问器的属性,这称为只写属性。只写属性不包含get访问器,对其进行读取操作会报告编译错误。只写属性适用于对密码这样的数据进行保护。

      属性在外观、行为和感觉上都像字段。但属性本质上是方法而不是字段。另外,属性存在以下限制:

      1、只有在结构或类初始化好之后,才能通过该结构或类的属性来赋值。

      ScreenPosition  location;

      location.X = 40;//编译错误,location尚未赋值

      2、不能将属性作为ref和out参数传给方法;但可写的字段能作为ref和out参数值传递。

      MyMethod(ref location.X);  //编译时错误

      3、属性中最多只能包含一个get和一个set访问器。不能包含其他方法、字段或属性。

      4、get和set访问器不能获取任何参数。要赋的值会通过内建的、隐藏的value变量自动传给set访问器。

      5、不能声明const属性。

      const int X{ get{...} set{...} }//编译错误

      在接口中声明属性

      除了可以在接口中定义方法之外,还可以定义属性。为此,需要指定get或set关键字,或者同时指定这两个关键字。但要将get或set访问器的主体替换成分号。如下:

      interface IScreenPosition

      {

      int X {get;set;} //没有修饰符

      int Y{get;set;} //没有修饰符

      }

      实现这个接口的任何类或结构都必须实现X和Y属性,并在属性中定义get和set访问器。如下:

      struct ScreenPosition: IScreenPosition

      {

      .............

      public int X

      {

      get{....}

      set{.....}

      }

      public int Y

      {

      get{....}

      set{.....}

      }

      ..............

      }

      在类中实现接口的属性时,可将属性的实现声明为virtual,从而允许派生类重写实现。如下:

      struct ScreenPosition: IScreenPosition

      {

      .............

      public virtual  int X

      {

      get{....}

      set{.....}

      }

      public virtual  int Y

      {

      get{....}

      set{.....}

      }

      ..............

      }

      还可使用显示接口实现语法来实现属性。属性的显示实现是非公共和非虚的(因而不能被重载)。

      生成自动属性

      C#编译器现在能自动为属性生成代码,如下:

      class Circle{

      public int Radius{ get; set; }

      ..........

      }

      在这个例子中,Circle类包含名为Radius的属性。除了属性的类型,不必指定这个属性是如何工作的——get和set访问器都是空白的。C#编译器自动将这个定义转换成私有字段以及一个默认的实现,如下所示:

      class Circle{

      private int _radius;

      public int Radius{

      get{ return this. _radius;}

      set{ this. _radius=value;}

      }

      .........

      }

      定义自动属性时,语法与在接口中定义属性几乎完全相同。区别在于,自动属性可以指定访问修饰符,例如private,public,或者protect。

      使用属性来初始化对象

      public class Triangle

      {

      private int side1Length = 10;

      private int side2Length = 10;

      private int side3Length = 10;

      public int side1Length

      {

      set{this. side1Length  = value;}

      }

      public int side2Length

      {

      set{this. side2Length  = value;}

      }

      public int side3Length

      {

      set{this. side3Length  = value;}

      }

      }

      创建类的实例时,可以提供了set访问器的任何公共属性指定名称和值。如下:

      Triangle tri1= new Triangle{side3Length  = 15;}

      Triangle tri2= new Triangle{side1Length  = 15;side3Length  = 20;}

      Triangle tri3= new Triangle{side2Length  = 15;side3Length  = 20;}

      Triangle tri4= new Triangle{side1Length  = 15;side2Length  = 15;side3Length  = 20;}

      这个语法称为对象初始化器。像这样调用对象初始化器,C#编译器会自动生成代码来调用默认构造器,然后调用每个具名属性的set访问器,把它初始化成指定值。还可将对象初始化器与非默认构造器配合使用。例如,假定Triangle类还有一个构造器能获取单个字符串参数(描述三角形的类型),那么可以调用这个构造器,同时对其他属性进行初始化;

      Triangle tri4= new Triangle("等边三角形"){side1Length  = 15;side2Length  = 15;side3Length  = 15;}

      对象初始化器与自动属性配合使用

      Polygon类

      using System;

      using System.Collections.Generic;

      using System.Linq;

      using System.Text;

      using System.Threading.Tasks;

      namespace AutomaticProperties

      {

      class Polygon

      {

      public int NumSides { get; set; }

      public double SideLength { get; set; }

      public Polygon()

      {

      this.NumSides = 4;

      this.SideLength = 10.0;

      }

      }

      }

      Program类

      using System;

      using System.Collections.Generic;

      using System.Text;

      namespace AutomaticProperties

      {

      class Program

      {

      static void doWork()

      {

      Polygon square = new Polygon();

      Polygon triangle = new Polygon { NumSides = 3 };

      Polygon pentagon = new Polygon { SideLength = 15.5, NumSides = 5 };

      Console.WriteLine("Square: number of sides is {0}, length of each side is {1}",

      square.NumSides, square.SideLength);

      Console.WriteLine("Triangle: number of sides is {0}, length of each side is {1}",

      triangle.NumSides, triangle.SideLength);

      Console.WriteLine("Pentagon: number of sides is {0}, length of each side is {1}",

      pentagon.NumSides, pentagon.SideLength);

      }

      static void Main(string[] args)

      {

      try

      {

      doWork();

      }

      catch (Exception ex)

      {

      Console.WriteLine(ex.Message);

      }

      }

      }

      }

      

  • 相关阅读:
    HTML
    JavaScript事件对象
    JavaScript 事件入门
    如何向github上传文件
    crystal
    BUUCTF[强网杯 2019]随便注wp
    BUUCTF[CISCN2019 华东南赛区]Web4 wp
    BUUCTF[NPUCTF2020]ezinclude wp
    Windows下Ant的环境配置
    Java解惑(1)——表达式之谜
  • 原文地址:https://www.cnblogs.com/linhuide/p/5819885.html
Copyright © 2020-2023  润新知