分享

get set访问器

 秋水风帆 2010-12-13

属性结合了字段和方法的多个方面。对于对象的用户,属性显示为字段,访问该属性需要相同的语法。对于类的实现者,属性是一个或两个代码块,表示一个 get 访问器和/或一个 set 访问器。当读取属性时,执行 get 访问器的代码块;当向属性分配一个新值时,执行 set 访问器的代码块。不具有 set 访问器的属性被视为只读属性。不具有 get 访问器的属性被视为只写属性。同时具有这两个访问器的属性是读写属性。

与字段不同,属性不作为变量来分类。因此,不能将属性作为 ref(C# 参考) 参数或 out(C# 参考) 参数传递。

属性具有多种用法:它们可在允许更改前验证数据;它们可透明地公开某个类上的数据,该类的数据实际上是从其他源(例如数据库)检索到的;当数据被更改时,它们可采取行动,例如引发事件或更改其他字段的值。

属性在类块中是按以下方式来声明的:指定字段的访问级别,接下来指定属性的类型和名称,然后跟上声明 get 访问器和/或 set 访问器的代码块。例如:

C#  “复制”图像复制代码
public class Date
            {
            private int month = 7;  //"backing store"
            public int Month
            {
            get
            {
            return month;
            }
            set
            {
            if ((value > 0) && (value < 13))
            {
            month = value;
            }
            }
            }
            }
            

在此示例中,Month 是作为属性声明的,这样 set 访问器可确保 Month 值设置为 1 和 12 之间。Month 属性使用私有字段来跟踪实际值。属性的数据的真实位置经常称为属性的“后备存储”。属性使用作为后备存储的私有字段是很常见的。将字段标记为私有可确保该字段只能通过调用属性来更改。有关公共和私有访问限制的更多信息,请参见 访问修饰符(C# 编程指南)

自动实现的属性提供用于简单属性声明的简化语法。有关更多信息,请参见自动实现的属性(C# 编程指南)

“折叠”图像get 访问器

get 访问器体与方法体相似。它必须返回属性类型的值。执行 get 访问器相当于读取字段的值。例如,当正在从 get 访问器返回私有变量并且启用了优化时,对 get 访问器方法的调用由编译器进行内联,因此不存在方法调用的系统开销。然而,由于在编译时编译器不知道在运行时实际调用哪个方法,因此无法内联虚拟 get 访问器。以下是返回私有字段 name 的值的 get 访问器:

C#  “复制”图像复制代码
class Person
            {
            private string name;  // the name field
            public string Name    // the Name property
            {
            get
            {
            return name;
            }
            }
            }
            

当引用属性时,除非该属性为赋值目标,否则将调用 get 访问器以读取该属性的值。例如:

C#  “复制”图像复制代码
Person p1 = new Person();
            //...
            System.Console.Write(p1.Name);  // the get accessor is invoked here
            

get 访问器必须以 returnthrow 语句终止,并且控制权不能离开访问器体。

通过使用 get 访问器更改对象的状态不是一种好的编程风格。例如,以下访问器在每次访问 number 字段时都会产生更改对象状态的副作用。

C#  “复制”图像复制代码
private int number;
            public int Number
            {
            get
            {
            return number++;   // Don't do this
            }
            }
            

get 访问器可用于返回字段值,或用于计算并返回字段值。例如:

C#  “复制”图像复制代码
class Employee
            {
            private string name;
            public string Name
            {
            get
            {
            return name != null ? name : "NA";
            }
            }
            }
            

在上一个代码段中,如果不对 Name 属性赋值,它将返回值 NA。

“折叠”图像set 访问器

set 访问器类似于返回类型为 void 的方法。它使用称为 value 的隐式参数,此参数的类型是属性的类型。在下面的示例中,将 set 访问器添加到 Name 属性:

C#  “复制”图像复制代码
class Person
            {
            private string name;  // the name field
            public string Name    // the Name property
            {
            get
            {
            return name;
            }
            set
            {
            name = value;
            }
            }
            }
            

当对属性赋值时,用提供新值的参数调用 set 访问器。例如:

C#  “复制”图像复制代码
Person p1 = new Person();
            p1.Name = "Joe";  // the set accessor is invoked here                
            System.Console.Write(p1.Name);  // the get accessor is invoked here
            

set 访问器中,对局部变量声明使用隐式参数名称 value 是错误的。

“折叠”图像备注

可将属性标记为 publicprivateprotectedinternalprotected internal。这些访问修饰符定义类的用户如何才能访问属性。同一属性的 getset 访问器可能具有不同的访问修饰符。例如,get 可能是 public 以允许来自类型外的只读访问;set 可能是 privateprotected。有关更多信息,请参见访问修饰符(C# 编程指南)

可以使用 static 关键字将属性声明为静态属性。这使得调用方随时可使用该属性,即使不存在类的实例。有关更多信息,请参见静态类和静态类成员(C# 编程指南)

可以使用 virtual 关键字将属性标记为虚属性。这样,派生类就可以通过使用 override 关键字来重写事件行为。有关这些选项的更多信息,请参见 继承(C# 编程指南)

重写虚属性的属性还可以是 sealed 的,这表示它对派生类不再是虚拟的。最后,可以将属性声明为 abstract。这意味着类中没有任何实现,派生类必须编写自己的实现。有关这些选项的更多信息,请参见 抽象类、密封类及类成员(C# 编程指南)

注意注意:

static 属性的访问器使用 virtual(C# 参考)abstract(C# 参考)override(C# 参考) 修饰符是错误的。

“折叠”图像示例 1

说明

此例说明了实例、静态和只读属性。它从键盘接受雇员的姓名,按 1 递增 NumberOfEmployees,并显示雇员的姓名和编号。

代码

C#  “复制”图像复制代码
public class Employee
            {
            public static int NumberOfEmployees;
            private static int counter;
            private string name;
            // A read-write instance property:
            public string Name
            {
            get { return name; }
            set { name = value; }
            }
            // A read-only static property:
            public static int Counter
            {
            get { return counter; }
            }
            // A Constructor:
            public Employee()
            {
            // Calculate the employee's number:
            counter = ++counter + NumberOfEmployees;
            }
            }
            class TestEmployee
            {
            static void Main()
            {
            Employee.NumberOfEmployees = 100;
            Employee e1 = new Employee();
            e1.Name = "Claude Vige";
            System.Console.WriteLine("Employee number: {0}", Employee.Counter);
            System.Console.WriteLine("Employee name: {0}", e1.Name);
            }
            }
            

“折叠”图像输出 1

Employee number: 101

Employee name: Claude Vige

“折叠”图像示例 2

说明

此示例说明如何访问基类中由派生类中具有同一名称的另一个属性所隐藏的属性。

代码

C#  “复制”图像复制代码
public class Employee
            {
            private string name;
            public string Name
            {
            get { return name; }
            set { name = value; }
            }
            }
            public class Manager : Employee
            {
            private string name;
            // Notice the use of the new modifier:
            public new string Name
            {
            get { return name; }
            set { name = value + ", Manager"; }
            }
            }
            class TestHiding
            {
            static void Main()
            {
            Manager m1 = new Manager();
            // Derived class property.
            m1.Name = "John";
            // Base class property.
            ((Employee)m1).Name = "Mary";
            System.Console.WriteLine("Name in the derived class is: {0}", m1.Name);
            System.Console.WriteLine("Name in the base class is: {0}", ((Employee)m1).Name);
            }
            }
            

“折叠”图像输出 2

Name in the derived class is: John, Manager

Name in the base class is: Mary

“折叠”图像代码讨论

以下是上一个示例中的要点:

  • 派生类中的属性 Name 隐藏基类中的属性 Name。在这种情况下,派生类的属性声明中使用 new 修饰符:

    C#  “复制”图像复制代码
    public new string Name
                    
  • 转换 (Employee) 用于访问基类中的隐藏属性:

    C#  “复制”图像复制代码
    ((Employee)m1).Name = "Mary";
                    

    有关隐藏成员的更多信息,请参见 new 修饰符(C# 参考)

“折叠”图像示例 3

说明

在此例中,CubeSquare 这两个类实现抽象类 Shape,并重写它的抽象 Area 属性。注意属性上 override 修饰符的使用。程序接受输入的边长并计算正方形和立方体的面积。它还接受输入的面积并计算正方形和立方体的相应边长。

代码

C#  “复制”图像复制代码
abstract class Shape
            {
            public abstract double Area
            {
            get;
            set;
            }
            }
            class Square : Shape
            {
            public double side;
            public Square(double s)  //constructor
            {
            side = s;
            }
            public override double Area
            {
            get
            {
            return side * side;
            }
            set
            {
            side = System.Math.Sqrt(value);
            }
            }
            }
            class Cube : Shape
            {
            public double side;
            public Cube(double s)
            {
            side = s;
            }
            public override double Area
            {
            get
            {
            return 6 * side * side;
            }
            set
            {
            side = System.Math.Sqrt(value / 6);
            }
            }
            }
            class TestShapes
            {
            static void Main()
            {
            // Input the side:
            System.Console.Write("Enter the side: ");
            double side = double.Parse(System.Console.ReadLine());
            // Compute the areas:
            Square s = new Square(side);
            Cube c = new Cube(side);
            // Display the results:
            System.Console.WriteLine("Area of the square = {0:F2}", s.Area);
            System.Console.WriteLine("Area of the cube = {0:F2}", c.Area);
            System.Console.WriteLine();
            // Input the area:
            System.Console.Write("Enter the area: ");
            double area = double.Parse(System.Console.ReadLine());
            // Compute the sides:
            s.Area = area;
            c.Area = area;
            // Display the results:
            System.Console.WriteLine("Side of the square = {0:F2}", s.side);
            System.Console.WriteLine("Side of the cube = {0:F2}", c.side);
            }
            }
            

输入

  “复制”图像复制代码
4
            24

“折叠”图像输出 3

Enter the side: 4

Area of the square = 16.00

Area of the cube = 96.00

Enter the area: 24

Side of the square = 4.90

Side of the cube = 2.00

“折叠”图像请参见

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多