只读字段

当字段声明中含有 readonly 修饰符时,该声明所引入的字段为只读字段。给只读字段的直接赋值只能作为声明的组成部分出现,或在同一类中的实例构造函数或静态构造函数中出现。(在这些上下文中,只读字段可以被多次赋值。)准确地说,只在下列上下文中允许对 readonly 字段进行直接赋值:

  • 在用于引入该字段的变量声明符中(通过添加一个变量初始值设定项)。
  • 对于实例字段,在包含字段声明的类的实例构造函数中;对于静态字段,在包含字段声明的类的静态构造函数中。也只有在这些上下文中,将 readonly 字段作为 out 或 ref 参数传递才有效。

在其他任何上下文中,试图对 readonly 字段进行赋值或将它作为 out 或 ref 参数传递都会导致一个编译时错误。

C#常量数据与只读字段

常量数据

C#提供了const关键字来定义常量,如果我们要为应用程序定义逻辑上和某个类或结构相关的一组已知值的话,就非常有用。

假如我们创建一个MyMathClass的工具类,且需要定义一个PI值(假如是3.14),如果不希望别的开发者改变PI值,可以使用如下常量定义PI值:

 class MyMathClass
{
//定义为常量数据
public const double PI=3.14;
}
class Program
{
public static void Main(string[] args)
{
//注意:因为常量数据是隐式静态的,所以只能直接在类级别上调用(MyMathClass.PI)。
Console.WriteLine("PI值是:{0}",MyMathClass.PI); //错误!常量数据不能被修改。
MyMathClass.PI=3.15;
Console.ReadLine();
}
}

注意:定义常量时必须为常量指定初始值,常量一旦定义就不能修改了。

 class MyMathClass
{
//尝试再构造函数中给常量赋值
public const double PI;
public MyMathClass()
{
//错误!
PI=3.14;
}
}

在编译时必须知道常量的值!

只读字段

和常量密切联系的概念是只读字段(不要和只读属性混淆哦,只读属性指只有get块的属性)。和常量相似,只读字段不能在赋值后改变。然而,和常量不同,赋值给只读字段可以在运行时决定。因此在构造函数作用域范围内给只读字段赋值是合法的(其他地方不行!)。

 class MyMathClass
{
//可以构造函数中为只读字段赋值,其他地方不行!
public readonly double PI;
public MyMathClass()
{
PI=3.14;
}
public void ChangePI()
{
//错误!
PI=3.14;
}
}

另:只读字段不是隐式静态的,要定义静态只读字段就需要使用static关键字了。

问题:请叙述const与readonly的区别。

const 关键字用于修改字段或局部变量的声明。它指定字段或局部变量的值不能被修改。常数声明引入给定类型的一个或多个常数,开心哦。const数据成员的声明式必须包含初值,且初值必须是一个常量表达式。因为它是在编译时就需要完全评估。const成员可以使用另一个const成员来初始化,前提是两者之间没有循环依赖。readonly在运行期评估赋值,使我们得以在确保“只读访问”的前提下,把object的初始化动作推迟到运行期进行。

readonly 关键字与 const 关键字不同: const 字段只能在该字段的声明中初始化。readonly 字段可以在声明或构造函数中初始化。因此,根据所使用的构造函数,readonly 字段可能具有不同的值。另外,const 字段是编译时常数,而 readonly 字段可用于运行时常数。readonly 只能在声明时或者构造函数里面初始化。

readonly的作用就是:一些变量,不允许别人修改,但是在声明的时候还不能对其赋值,所以不能用const常亮。这时可以用readonly关键字,在类的构造函数中对这些变量赋值。

枚举与常量需要注意的一个问题

.net中枚举其实就是数值型的常量,与const类似。当我们在代码中使用枚举代表的数值或者常量时,编译器其实是将该值直接写过来,而不会在运行的时候去读取该值。下面是一个例子:

我们想建立一个类库项目,名称叫ClassLibrary1,再建立一个控制台项目,名称叫ConsoleApplication2,结构如下:

ClassLibrary1项目中Class1中的代码是:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace ClassLibrary1
{
public class MyClass
{
public static string str1 = "str1";
public const string str2 = "str2";
} public enum MyEnum
{
One = ,
Two = ,
Three =
}
}

定义了一个枚举以及一个静态字段、一个常量字段。

ConsoleApplication2项目引用A项目,代码如下:

 using System;
using ClassLibrary1; class Program
{
public static void Main(string[] args)
{
Console.WriteLine((int)MyEnum.One);
Console.WriteLine(MyEnum.One.ToString()); Console.WriteLine(MyClass.str1);
Console.WriteLine(MyClass.str2); Console.ReadKey();
}
}

我们来看看Program类用Reflector工具反编译后的样子:

public class MyClass
{
// Fields
public static string str1;
public const string str2 = "str2"; // Methods
static MyClass();
public MyClass();
} 注意:这里自动的添加了两个构造函数,一个静态一个非静态。
 public static void Main(string[] args)
{
Console.WriteLine();
Console.WriteLine(MyEnum.One.ToString());
Console.WriteLine(MyClass.str1);
Console.WriteLine("str2");
Console.ReadKey();
}

编译器将(int)MyEnum.One的值与常量字段str2直接硬编码写到代码中,而不是在运行期再去读取。

这样处理的后果是:如果你修改了A项目中的枚举的排列顺序或者枚举对应的值(或者改变了常量字段str2的值),比如将MyEnum.One的值2,同时不重新编译Test项目,那样运行结果还是不会变的。

Programming C#.Classes and Objects.只读字段的更多相关文章

  1. Programming C#.Classes and Objects.成员方法

    this关键字指向类的当前实例,this指针是类中所有非静态方法的隐藏指针,每个方法都能通过this指针指向对象的其他方法和成员变量. 因为对一个类来说,它的成员函数(方法)只有一份,所有的实例对象共 ...

  2. Programming C#.Classes and Objects.传递参数

    ref 关键字通过引用(而非值)传递参数. 通过引用传递的效果是,对所调用方法中的参数进行的任何更改都反映在调用方法中. 说明: 不要混淆通过引用传递的概念与引用类型的概念. 这两种概念是不同的. 无 ...

  3. 破解C#的readonly只读字段

    破解C#的readonly只读字段 目录 请允许我再唠叨几句const和readonly 修改readonly字段: 计策1:反间计 -- 反射修改 计策2:借刀杀人--调节字段偏移位置的结构体来修改 ...

  4. c#基础--常量(const),只读字段(readonly)

    1.0:常量 常量被关键字const 所修饰 我们来看看常量的demo class Program { static void Main(string[] args) { const string n ...

  5. C#编程(十五)----------只读字段

    只读字段 当字段声明中含有 readonly 修饰符时,该声明所引入的字段为只读字段.给只读字段的直接赋值只能作为声明的组成部分出现,或在同一类中的实例构造函数或静态构造函数中出现.(在这些上下文中, ...

  6. Reloading Java Classes 101: Objects, Classes and ClassLoaders Translation

    The original link: http://zeroturnaround.com/rebellabs/reloading-objects-classes-classloaders/ A Bir ...

  7. c#只读字段和常量的区别,以及静态构造函数的使用 .

    using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace Console ...

  8. Classes as objects

    Before understanding metaclasses, you need to master classes in Python. And Python has a very peculi ...

  9. 只读字段(readonly)和常量(const)

    1.常量 一个包含不能修改的值的变量,通过const关键字定义.只能在声明的同时赋值 2.只读字段 通过readonly关键字定义. 可以在声明的同时赋值. 对于实例字段,在包含字段声明的类的实例构造 ...

随机推荐

  1. RDLC报表系列(三) 总计和折叠

    继续接上一篇的内容,本文主要是简述总计和折叠 1.在Dept列右击,选择插入行->组内部下方(每个部门的Total),插入新的一行,并拆分单元格,然后合并列 3.设置文本框属性,格式为Total ...

  2. python基础之 re(正则表达式)模块学习

    今天学习了Python中有关正则表达式的知识.关于正则表达式的语法,不作过多解释,网上有许多学习的资料.这里主要介绍Python中常用的正则表达式处理函数. re.match re.match 尝试从 ...

  3. Java多线程并发编程之原子变量与非阻塞同步机制

    1.非阻塞算法 非阻塞算法属于并发算法,它们可以安全地派生它们的线程,不通过锁定派生,而是通过低级的原子性的硬件原生形式 -- 例如比较和交换.非阻塞算法的设计与实现极为困难,但是它们能够提供更好的吞 ...

  4. eclipse 使用maven 创建纯spring mvc项目

    接着eclipse 使用maven 创建web3.1项目 创建完成后, 讲spring mvc加入到项目中 先修改pom.xml文件 注意红色字部分 <project xmlns="h ...

  5. Android之修改部分字体颜色

    #01# 方法一: TextView textView = (TextView) view.findViewById(R.id.text); SpannableString ss = new Span ...

  6. Flink Program Guide (3) -- Event Time (DataStream API编程指导 -- For Java)

    Event Time 本文翻译自DataStream API Docs v1.2的Event Time ------------------------------------------------ ...

  7. 通过实例深入理解lec和yacc

    本框架是一个lex/yacc完整的示例,包括详细的注释,用于学习lex/yacc程序基本的搭建方法,在linux/cygwin下敲入make就可以编译和执行.大部分框架已经搭好了,你只要稍加扩展就可以 ...

  8. 离线使用nuget

    先新建一个项目,将所有想保存下来或者要升级的package先安装或升级. 然后在项目中将packages文件夹全部拷贝出来,专门放到一个目录备用,以后的项目就可以根据此packages文件夹来离线使用 ...

  9. html5 OPOA

    1.0 one page one application     一个应用只有一个页面,对用户的表现来说的. 2.0 起源于web的MIS系统     MIS(管理信息系统) 3.0 银行客户端 4. ...

  10. python---连接MySQL第一页

    前言:python如果想要连接到MySQL要安装上相关的驱动才下:好在驱动程序在mysql的官网可以下载的到. 以下是我自己保存的一个conetos7版本 http://yunpan.cn/cLACS ...