只读字段

当字段声明中含有 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. CSS学习笔记(1):选择器

    一.元素选择器 HTML文档元素就是最基本的选择器 如: <!DOCTYPE html> <html lang="en"> <head> < ...

  2. ChildNodes详解及其兼容性处理方式

    写在前面:在做insertBefore插入节点练习时发现一个问题,插入childNodes[0]和childNodes[1]时插入的位置是一样的!于是有了childNodes的了解,有了这篇文章,欢迎 ...

  3. 百度编辑器ueditor 在vs2008中的使用方法

    个人觉得百度编辑器ueditor还是不错的,虽然出生的时间比较短,但某些方面相比其它富文本编辑器更优秀,免费.可定制等等. 由于在官方下载的ueditor包是在vs2012下开发的,可以在vs2010 ...

  4. Android布局(一)layout_gravity 属性和 gravity属性的区别

    安卓中的 layout_gravity 属性和 gravity属性 有啥区别? LinearLayout有两个非常相似的属性: android:gravity与android:layout_gravi ...

  5. SQL Server 2012 Enterprise Edition安装过程详解(包含每一步设置的含义)

    一.启动安装程序,点击“安装”选项卡,选择“全新SQL Server独立安装或向现有安装添加功能”.(首次安装数据库系统或向现有数据库系统添加功能,均选择此选项) 二.随后,安装程序进行“安装程序支持 ...

  6. 如何对MySQL 对于大表(千万级)进行优化

    如何对Mysql中的大型表进行优化 @(mysql 笔记) 收集信息 1.数据的容量:1-3年内会大概多少条数据,每条数据大概多少字节: 2.数据项:是否有大字段,那些字段的值是否经常被更新: 3.数 ...

  7. discuz二次开发笔记(二)------跳转函数运用

    前几天在增加修改功能时,突然用到一个提示函数,有点不理解,看了他的由来后果断做下笔记,感觉这在以后的开发中肯定还是要用的上的.有些地方不是很理解,在以后慢慢纠正.查补. Htm页面中用的js跳转: $ ...

  8. ThinkPHP框架下基于RBAC的权限控制模式详解

    这几天因为要做一个项目,需要可以对Web应用中通用功能进行封装,其中一个很重要的涉及到了对用户.角色和权限部分的灵活管理.所以基于TP框架自己封装了一个对操作权限和菜单权限进行灵活配置的可控制模式. ...

  9. jquery.lazyload.js图片延迟加载(懒加载)--转载

    一.插件介绍 jquery.lazyload.js 是一个用 JavaScript 编写的jQuery 插件. 它可以延迟加载长页面中的图片. 在浏览器可视区域外的图片不会被载入, 直到用户将页面滚动 ...

  10. CSS预处理器实践之Sass、Less比较

    什么是CSS预处理器? CSS可以让你做很多事情,但它毕竟是给浏览器认的东西,对开发者来说,Css缺乏很多特性,例如变量.常量以及一些编程语法,代码难易组织和维护.这时Css预处理器就应运而生了.Cs ...