只读字段

当字段声明中含有 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. [LeetCode] Search in Rotated Sorted Array [35]

    题目 Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 m ...

  2. stage.width/height和stage.stageWidth/stageHeight的区别

    stage.stageWidth和stage.stageHeight就是舞台的宽带和高度 一般默认打开宽带是550,高度是400 那么stage.stageWidth=550,stage.stageH ...

  3. 【SDK编程】

    #include <stdio.h> #include <windows.h> int main() { DeleteFile("C:\\test.txt" ...

  4. IDE idea 更换项目的JDK步骤

    1.如图:

  5. foreach 和for语句比较

    1.首先想到循环就是执行效率的问题,参考博客http://www.cnblogs.com/yzxchoice/archive/2007/12/15/995949.html 2. 测试时候发现出现“   ...

  6. 对于deferred的一点点理解

    deferred对象,是一个异步队列.能够实现异步代码调用,从而解决代码执行顺序的问题. 它提供了一下主要方法: jQuery.Deferred() 一个构造函数,返回一个链式实用对象方法来注册多个回 ...

  7. Js闭包的用途

    本来想总结一点JavaScript中的闭包的一些用法,在查资料的时候发现了一篇很好的文章,就转过来收藏了,下面附上传送门: js闭包的用途 ---------sunlylorn 我们来看看闭包的用途. ...

  8. css系列教程--css文件的创建

    css文件的创建:1.外部样式表:<link rel="stylesheet" type="text/css" href="mystyle.cs ...

  9. 【视图】实时库存【SSKC】

    select A.pluno,A.pluname,A.qty,CASE WHEN b.QTY IS NULL THEN 0 ELSE B.QTY   END  AS XSQTY ,case when ...

  10. ajax应用篇

    ajax简介 AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术.Ajax不是一种新的编程语言, ...