在C#中我们可以很自由的访问共有字段,但有时我们可能需要某字段只能读或者写,或在改变字段值得时候做一些其他事情,显然这些仅仅依靠字段是无法实现的,于是便有了属性。
1、基本用法
c#中的属性由属性作用域中定义的get作用域(访问方法)和set作用域(访问方法)构成。
class Test { private int number; //int表示该属性所封装的数据类型 //数据类型必须与相应的字段(number)相同 public int Num { get{return number;} set{number=value;} } }
当封装数据时,可能希望配置一个只读属性。为此,可以忽略set块。类似,如果想拥有一个只读属性,就忽略get块。
2、静态属性
C#静态属性可以是读写属性,只读属性,只写属性中的任意一种。静态访问器适用于整个类,而不是类的实例。静态属性中的set,get访问器只能访问类的静态成员。静态属性可以通过类名访问,不能使用实例调用,这与静态方法相同。
1 //简单的储蓄账户类 2 class SavingAccount 3 { 4 //实例级别的数据 5 public double currBalance; 6 7 //静态数据点 8 private static double currInterestRate = 0.04; 9 10 //静态属性 11 public static double InterestRate 12 { 13 get{return currInterestRate;} 14 set{currInterestRate=value;} 15 } 16 }
3、自动属性
自动属性可以简化封装数据字段的过程,减轻了定义私有返回字段和相关c#属性成员的工作。在定义自动属性时,只指定访问修饰符、实际的数据类型、属性名称和空的get/set作用域。在编译时,编译器为类型自动生成了私有返回字段和适当的get/set实现逻辑。
1 class Enemy 2 { 3 //自动属性 4 public string Name{get;set;} 5 public int Life{get;set;} 6 public float Attack{get;set;} 7 8 }
注意:与传统的属性不同的是,不允许构建只读或只写的自动属性,自动属性定义是必须同时支持读写功能。但是定义更严格的get或set是可以的
4、关于自动属性和默认值
可以直接在代码中使用封装了数字或布尔数据的自动属性,因为隐藏的返回字段将设置一个可以直接使用的安全的默认值。但如果自动属性封装了另一个类变量,隐藏的私有引用类型的默认值将设为null。
例如下面的类spawn,使用了两个自动属性
1 class Spawn 2 { 3 //隐藏的int字段默认值为0 4 public int numbers{get;set;} 5 //隐藏的Enemy返回字段为null 6 public Enemy MyEnemy{get;set;} 7 }
当直接调用MyEnemy时,将会在运行时得到空引用异常,因为没有为后台使用的Enemy成员变量设置新的对象。
由于私有的返回字段是在编译时创建的,所以不能直接使用new关键字直接分配引用类型,必须在类的构造函数内部执行,以确保对象以安全方式诞生。
1 class Spawn 2 { 3 //隐藏的int字段默认值为0 4 public int numbers{get;set;} 5 //隐藏的Enemy返回字段为null 6 public Enemy MyEnemy{get;set;} 7 8 //必须用构造函数重写分配给隐藏返回字段的默认值 9 public Spawn() 10 { 11 MyEnemy = new Enemy(); 12 numbers = 1; 13 } 14 15 public Spawn(Enemy enemy, int num) 16 { 17 MyEnemy = enemy; 18 numbers = num; 19 } 20 }