【C#语言入门】14. 字段,属性,索引器,常量
一、字段
- 什么是字段
- 字段(field)是一种表示与对象或者类型(类与结构体)关联的变量
- 字段是类型的成员,旧称“成员变量”
- 与对象关联的字段亦称“实例字段”
- 与类型关联的字段称为“静态字段”,由static修饰
class Student
{
public int Age;
public int Score;
public static int AverageAge;
public static int AverageScore;
public static int Amount;
public Student()
{
Student.Amount++;
}
public static void ReportAmount()
{
Console.WriteLine(Student.Amount);
}
}
-
字段的声明
- 字段是类型的成员,所以要写在类体里面,而不是在函数体里面。
- attributesopt field-modifiersopt type variable-declaratiors ;
- 只读(readonly)字段可以接受初始化,但不能修改。
- 尽管字段声明带有分号,但是它不是语句,语句存在于方法体中。
- 字段的名字一定是名词。
-
字段的初始值
- 无显式初始化时,字段获得其类型的默认值,所以字段永远不会未被初始化。
- 实例字段初始化的时机——对象创建时。
- 静态字段初始化的时机——类型被加载(load)时。
-
只读字段
- 实例只读字段(直接写后面,或者实例构造器)
- 静态只读字段(直接写后面,或者静态构造器)
二、属性
- 什么是属性
- 属性(property)是一种用于访问对象或者类型的特征的成员,特征反应了状态。
- 属性是字段的自然扩展
- 从命名上看,field更偏向于实例对象在内存中的布局,property更偏向于反映现实世界对象的特征
- 对外:暴露数据,数据可以是存储在字段里面的,也可以是动态计算表出来的
- 对内:保护字段不被非法值“污染”
- 属性由Get/Set方法对进化而来
- 又一个“语法糖”——属性背后的秘密(语法糖是指用简单的表示复杂的逻辑)
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student();
stu1.SetAge(20);
Student stu2 = new Student();
stu2.SetAge(20);
Student stu3 = new Student();
stu3.SetAge(20);
int avgAge = (stu1.GetAge() + stu2.GetAge() + stu3.GetAge())/3;
Console.WriteLine(avgAge);
}
}
class Student
{
private int age;
public int GetAge()
{
return int this.age;
}
public void SetAge(int value)
{
if(value>0 && value<=120)
{
this.age = value;
}
else
{
throw new Exception("Age value has error.");
}
}
}
属性↓
class Program
{
static void Main(string[] args)
{
try
{
Student stu1 = new Student();
stu1.Age = 20;
Student stu2 = new Student();
stu2.Age = 20;
Student stu3 = new Student();
stu3.Age = 20;
int avgAge = (stu1.Age + stu2.Age + stu3.Age)/3;
Console.WriteLine(avgAge);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
class Student
{
private int age;
public int Age
{
get
{
return this.age;
}
set
{
if(value>0 && value<=120)
{
this.age = value;
}
else
{
throw new Exception("Age value has error.");
}
}
}
}
-
属性的声明
- 完整声明——后台(back)成员变量与访问器(注意使用code snippet和refactor工具)(propfull+双回车)
- attributesopt field-modifiersopt type member-name { accessor-declarations }
- 简略声明——只有访问器(prop+双回车)
- 动态计算值的属性
- 注意实例属性和静态属性
- 属性的名字一定是名词
- 只读属性——只有getter没有setter
- 尽管语法上正确,但几乎没有人使用“只写属性”,因为属性的主要目的是通过向外暴露数据而表示对象/类型的状态
-
属性与字段的关系
- 一般情况下,他们都用于表示实体(对象或类型)的状态
- 属性大多数情况下是字段的包装器(wrapper)
- 建议:永远使用属性(而不是字段)来暴露数据,即字段永远都是private或者protected的
三、索引器(概述)
- 什么是索引器
- 索引器(indexer)是这样一种成员:它使对象能够用于数组相同的方式(即使用下标)进行索引(indexer+双回车)
class Student
{
private Dictionary<string, int> scoreDictionary = new Dictionary<string, int>();
public int? this[string subject]
{
get
{
if(this.scoreDictionary.ContainKey(subject))
{
return this.scoreDictionary(subject);
}
else
{
return null;
}
}
set
{
if(value.HasValue == false)
{
throw new Exception("Score cannot be null.");
}
if(this.scoreDictionary.ContainsKey(subject))
{
this.scoreDictionary(subject) = value.Value;
}
else
{
this.scoreDictionary.Add(subject, value.Value);
}
}
}
}
四、常量
-
什么是常量
- 常量(cosntant)是表示常量值(即,可以在编译时计算的值)的类成员。
- 常量隶属于类型而不是对象,即没有“实例常量”。但是可以用只读实例字段充当“实例常量”
- 注意区分成员常量和局部常量。
-
常量的声明
-
各种“只读”的应用场景
- 为了提高程序可读性和执行效率——常量
- 为了防止对象的值被改变——只读字段
- 向外暴露不允许修改的数据——只读属性(静态或非静态),功能与常量有一些重叠
- 当希望成为常量的值其类型不能被常量声明接受时(类/自定义结构体)——静态只读字段
class Program
{
static void Main(string[] args)
{
Console.WriteLine(WASPEC.WebsiteURL);
}
}
class WASPEC
{
public const string WebsiteURL = "http://www.waspec.org";
}