字段(field)是类中最常见的成员之一。C# 支持静态字段(类型字段)和实例字段,而上一节《C# const》中介绍的常量属于特殊的静态字段。
对于实例字段,其内存在创建实例时动态分配,而对于静态字段,其内存在类型对象创建时分配。
类型对象是类型加载到一个应用程序域(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; }
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/22365.html