02010701 深入理解类01-静态成员、字段与属性关联
1. 静态成员
-
类可以拥有静态字段。静态字段被类所有的实例所共享,所有的实例 都访问同一内存位置。如果该内存位置的值被一个实例改变了,这种改变对所有的实例都可见。
-
从类的外面访问静态成员,通常直接使用类名类访问。
// 访问静态成员的方式1:通过类名来访问
class MyClass
{int MyClassComm; // 实例字段,通过类的实例来访问int MyClassStatic; // 静态字段,可以通过类名来访问,也可以通过实例来访问staitc public void MyFunc(); // 静态方法,可以通过类名访问,也可以直接访问。{...}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 访问静态成员的方式2:通过using static声明来访问
using static System.Console;
WriteLine(“...”);上述语句等价于下面语句using System;
Console.WriteLine("...")
2. 静态成员的生存期
- 静态成员的生命周期与实例成员不同。
- 只有在实例创建之后才产生实例成员,在实例销毁之后实例成员也就不存在了。
- 即使类没有实例,也存在静态成员,并且可以访问。如果静态字段有初始化语句,那么会在使用该类的任何静态成员之前初始化该字段。
- 注意:并不一定在程序执行的开始就初始化静态字段。
3. 静态函数成员
- 静态函数成员独立于任何类实例,即使没有类的实例,仍然可以调用静态方法。
- 静态函数成员不能访问实例成员,但能访问其它静态成员。
4. 其它静态类成员类型
- 如下表为可以声明为static的类成员,其它成员类型不能声明为static。

5. 成员常量
- 成员常量被声明在类声明中,而不是在方法声明中。
class MyClass
{const int IntVal01 = 100; // 成员常量const int IntVal02 = IntVal01 * 2; // 正确写法,前一行已经定义了IntVal01的值// const int IntVal02; // 错误,必须初始化// IntVal02 = 10; // 错误,不允许被赋值
}说明:
1. 用于初始化成员常量的值在编译时必须是可计算的,而且通常是一个预定义简单类型或由它们组成的表达式。
2. 与C或C++不同,C#没有全局常量,C#的每个常量都必须声明在类当中。
6. 常量与静态量
- 成员常量表现的像静态值,它们对类的每个实例都是可见的,成员常量即使没有类的实例也可以使用。
- 成员常量与静态量的不同在于,常量在堆中没有自己的存储位置,在编译的时候常量会被编译器替换。
- 虽然成员常量表现的像静态量,但是不能将其声明为static。
// static const double PI = 3.14; // 错误写法
7. 属性
7.1 属性与字段对比
- 类属性和字段的核心区别在于属性通过访问器方法封装字段,而字段直接存储数据。
- 字段 → 直接存储数据,通常为private,以实现封装。
- 属性 → 通常关联私有字段,属性则是通过get和set方法控制对字段的访问。可控制访问权限:如类的外部只读,类的内部可修改。
- 属性相比字段提供如下优势。
- 封装性:隐藏字段细节,防止外部直接修改。
- 灵活性:支持读写逻辑控制(如空值检验,权限验证)。
- 兼容性:修改字段时无需修改外部接口代码。
7.2 属性的特点
- 属性有命名的类成员,设置为private(默认可以不写)。
- 属性有类型。
- 属性可以被赋值和读取。
7.3 属性声明
// 类属性声明
class MyClass
{int MyVal{set{...} get{...}}
}
7.4 访问器
-
属性是一组(2个)匹配的,命名的,称为访问器的方法。
- set访问器为属性赋值。可以把set访问器想象成一个方法,带有单一的参数,它设置属性的值。set访问器有如下特点。
- 拥有一个单独的,隐式的值参,名称为value,这个值参与属性的类型相同。
- set访问器中的隐式参数value是一个普通的值参,可以用它发送数据到方法体活访问器块。
- 在块的内部,可以像普通变量那样使用value,包括对它赋值。
- 拥有一个返回类型void。
- 拥有一个单独的,隐式的值参,名称为value,这个值参与属性的类型相同。
- get访问器从属性获取值。get访问器没有参数并从属性返回一个值。get访问器有如下特点。
- 没有参数。
- 拥有一个与属性类型相同的返回类型。
- set访问器为属性赋值。可以把set访问器想象成一个方法,带有单一的参数,它设置属性的值。set访问器有如下特点。
-
访问器的其它特点如下。
- get访问器的所有执行路径必须包含一条return语句,它返回一个属性类型的值。
- 访问器set和get可以以任何顺序声明,并且除了这两个访问器之外,属性上不允许有其它方法。
7.5 属性示例
class MyClass
{private int MyValue01; // 字段,分配内存,不初始化那么为值类型或引用类型的默认值。public int MyValue02 // 属性,未分配内存{set{MyVal02 = value;}get{return MyValue02;}}
}说明:
1. 属性本身没有任何存储。访问器决定如何处理发送进来的数据,以及将什么数据发送出去,在这种情况下,属性使用一个名为MyValue02的字段用来存储数据。
2. set访问器只用来接受它的输入参数value,并把这个value的值赋值给字段MyValue02.
3. get访问器只是返回字段MyValue02的值。
7.6 使用属性
- 属性会根据是写入还是读取来隐式的调用适当的访问器,注意不能显式的调用访问器,不然会产生编译错误。
int MyValue
{get{}set{}
}MyValue = 5; // 给属性赋值,隐式调用set方法。
z = MyValue; // 读取属性的值,隐式调用get方法。// y = MyValue.get(); // 错误写法,不能显示的调用get访问器。
// MyValue(5); // 错误写法,不能显示的调用set访问器。说明:
1. 要写入一个属性,在赋值语句左边使用属性的名称。
2. 要读取一个属性,把属性的名称用在"="右边的表达式中。
7.7 属性和关联字段
- 属性场合字段关联,一种常见的方式是在类中将字段声明为private以封装该字段。并声明一个public属性来控制从类外部对该字段的访问。和属性关联的字段常被称为后备字段或后备存储。
- 属性和它们后备字段命名约定,即属性和字段使用相同的字母名称,但是字段使用Camel大小写,属性使用Pascal大小写。
- Camel大小写 → 标识符中除了第一个单词小写,其它每个单词的首字母大写。
- Pascal大小写 → 标识符中每个单词首字母都是大写。
// 属性关联字段示例
private int firstField; // 字段使用Camel大小写
public int FirstField // 属性使用Pascal大小写
{get{return firstField;}set(firstField = value;)
}
7.8 只读和只写属性
- 只读属性 → 只有get访问器的属性称为只读属性。只读属性能安全的将一个数据项从类或类的实例中传出,不让调用者修改属性的值。
- 只写属性 → 只有set访问器的属性称为只写属性。只写属性几乎没有实际用途,很少见。
7.9 属性与公有字段对比
- 属性是函数成员而不是数据成员,允许处理输入和输出,而公有字段不行。
- 属性可以只读或只写,而字段不行。
- 编译后的变量和编译后的属性语义不同。(在后续会慢慢体会)
7.10 自动实现属性
- 因为属性经常被关联到后备字段,因此C#提供了自动实现属性(简称自动属性)。允许只声明属性,而不声明后备字段,此时编译器会为你创建隐藏的后备字段,并自动挂在到get和set访问器上。
- 从C# 6.0开始,可以使用自动实现属性,要点如下。
- 不声明后备字段 → 编译器根据属性的类型自动分配存储。
- 不提供访问器的方法体 → 此时方法体被简单的声明为“;”。
class MyClass{// 此处没有声明后备字段public int MyValue // 自动实现属性{set; get; // 使用";"替代方法体。}
}
7.11 静态属性
-
属性也可以声明为static,静态属性的访问器和所有静态成员一样,具有如下特点。
- 静态属性不能访问类的实例成员,但是能被类的实例成员访问。
- 不管是否有实例,静态属性都存在。
- 在类的内部,可以仅使用名称来引用静态成员。
- 在类的外部,可以通过类名或using static结构来引用静态属性。
结尾
书籍:C#图解教程
著:【美】丹尼尔 · 索利斯;卡尔 · 施罗坦博尔
译:窦衍森;姚琪琳
ISBN:978-7-115-51918-4
版次:第5版
发行:人民邮电出版社
※敬请购买正版书籍,侵删请联系85863947@qq.com※
※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※