C#字段(field)
字段(field)是类中最常见的成员之一。C# 支持静态字段(类型字段)和实例字段,而上一节《C# const》中介绍的常量属于特殊的静态字段。
对于实例字段,其内存在创建实例时动态分配,而对于静态字段,其内存在类型对象创建时分配。
类型对象是类型加载到一个应用程序域(AppDomain) 时创建的。
如果试图在构造函数之外的地方修改只读字段,就会发生编译错误。
不过,反射可以修改只读字段(实际上,没有什么是反射改不了的)。
只读字段和常量很像,但也有如下区别:
假设直到运行时才知道值(例如通过读取外部数据库),并且希望之后值不会被改变,那么只读字段就很有用。
如果想将只读字段设置为静态的,而且也是直到运行时才知道值, 那么需要使用静态构造函数为其赋值。
注意,即使对于引用类型的只读字段,我们也可以更改引用类型引用对象的值,但是, 我们不能更改引用类型的引用本身。
下面的代码中,我们试图更改一个只读字符串字段的值,但是,更改字符串的值,实质上是在字符串池中新建一个字符串,并将栈上原字符串的变量指向堆中新的字符串,即为更改引用。所以,这是不可以的。
对于实例字段,其内存在创建实例时动态分配,而对于静态字段,其内存在类型对象创建时分配。
类型对象是类型加载到一个应用程序域(AppDomain) 时创建的。
只读字段
由 readonly (只读)修饰的字段只能在定义时或构造函数中赋值。如果试图在构造函数之外的地方修改只读字段,就会发生编译错误。
不过,反射可以修改只读字段(实际上,没有什么是反射改不了的)。
只读字段和常量很像,但也有如下区别:
- 常量兼有只读和静态,所以常量一定是静态的,但只读字段不一定是。
- 只读字段可以在运行时决定(例如在构造函数中赋值),而常量必须在定义时就赋值。
- 只读字段可修饰任何类型,常量字段虽然也可以修饰任何类型,但对于非基元类型, 它的值必须为 null,因此没有什么用。
假设直到运行时才知道值(例如通过读取外部数据库),并且希望之后值不会被改变,那么只读字段就很有用。
如果想将只读字段设置为静态的,而且也是直到运行时才知道值, 那么需要使用静态构造函数为其赋值。
注意,即使对于引用类型的只读字段,我们也可以更改引用类型引用对象的值,但是, 我们不能更改引用类型的引用本身。
下面的代码中,我们试图更改一个只读字符串字段的值,但是,更改字符串的值,实质上是在字符串池中新建一个字符串,并将栈上原字符串的变量指向堆中新的字符串,即为更改引用。所以,这是不可以的。
class Program { static void Main(string[] args) { A a = new A(); a.print(); //0 //可以更改引用对象成员的值 a.field.b = 999; a.print(); //999 //但是不可以更改引用本身 //a.field = new B(); //a.str = "hello"; Console.ReadKey(); } } class A { public readonly B field; public readonly string str; public A() { field = new B(); } public void print() { Console.WriteLine(field.b); } } class B { public double b; }
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算