[转帖]C# const和static readonly有什么区别?
[转帖]C# const和static readonly有什么区别?
const和static readonly(一) 二者本质的区别在于,const的值是在编译期间确定的,因此只能在声明时通过常量表达式指定其值。而static readonly是在运行时计算出其值的,所以还可以通过静态构造函数来赋值。 本例利用前后两个程序段的对比,来区别const和static readonly。 测试类: using System;
using System.Collections.Generic; using System.Text; namespace Example02Lib { public class Class1 { public const String strConst = "Const"; public static readonly String strStaticReadonly = "StaticReadonly"; //public const String strConst = "Const Changed"; //public static readonly String strStaticReadonly = "StaticReadonly Changed"; } } 客户端代码: using System;
using System.Collections.Generic; using System.Text; using Example02Lib; namespace Example02 { class Program { static void Main(string[] args) { //修改Example02中Class1的strConst初始值后,只编译Example02Lib项目 //然后到资源管理器里把新编译的Example02Lib.dll拷贝Example02.exe所在的目录,执行Example02.exe //切不可在IDE里直接调试运行因为这会重新编译整个解决方案!! //可以看到strConst的输出没有改变,而strStaticReadonly的输出已经改变 //表明Const变量是在编译期初始化并嵌入到客户端程序,而StaticReadonly是在运行时初始化的 Console.WriteLine("strConst : {0}", Class1.strConst); Console.WriteLine("strStaticReadonly : {0}", Class1.strStaticReadonly); Console.ReadLine(); } } } 执行结果: strConst : Const strStaticReadonly : StaticReadonly 修改后的示例: 测试类: using System;
using System.Collections.Generic; using System.Text; namespace Example02Lib { public class Class1 { //public const String strConst = "Const"; //public static readonly String strStaticReadonly = "StaticReadonly"; public const String strConst = "Const Changed"; public static readonly String strStaticReadonly = "StaticReadonly Changed"; } } 执行结果: strConst : Const strStaticReadonly : StaticReadonly Changed const、readonly和static(二) 在第四节中,我介绍了常量的定义,其关键字就是const。在定义常量时,必须赋予其初始值。一旦赋予了初始值后,就不能修改其值。也就是所谓的常量值不能更改的含义。由于C#是一门纯粹的面向对象语言,并不存在一个常量或者变量游离于对象之外,因此,这些定义,必然都是在一个类型内完成的。 关于常量的使用,除了会用作一些算法的临时常量值以外,最重要的是定义一些全局的常量,被其他对象直接调用。而集中这些常量最好的类型是struct(结构)。关于struct我会在后面的章节详细讲解,在这里仅举一例说明常量的这种运用。例如,我们需要在.Net下使用FTP,那么一些特定的FTP代码就可以通过这种方式完成定义,如下所示: public struct FtpCode
{ public const string ConnectOk = "220"; public const string RequiredPassword = "331"; public const string LoginOk = "230"; public const string PasvOk = "227"; public const string CwdOk = "250"; public const string PwdOk = "257"; public const string TransferOk = "226"; public const string ListOk = "150"; public const string PortOK = "200"; public const string NoFile = "550"; }
虽然说变量的值可以修改,但我们也可以定义只读的变量,方法就是在定义的时候加上关键字readonly。如下定义: public readonly int number = 20;
static的意义与const和readonly迥然不同。const仅用于常量定义,readonly仅用于变量定义,而static则和常量、变量无关,它是指所定义的值与类型有关,而与对象的状态无关。 前面我已介绍,所谓“对象”,可以称为一个类型的实例,以class类型为例,当定义了一个类类型之后,要创建该类型的对象,必须进行实例化,方可以调用其属性或者方法。例如User类型的Name、Password属性,SignIn和SignOut方法,就都是与对象相关的,要调用这些属性和方法,只能通过实例化对象来调用,如下所示: User user = new User();
user.Name = "bruce zhang"; user.Password = "password"; user.SignIn(); user.SignOut();
public class LogManager
{ public static void Logging(string logFile,string log) { using (StreamWriter logWriter = new StreamWriter(logFile,true)) { logWriter.WriteLine(log); } } }
所谓“与对象状态无关”,还需要从实例化谈起。在对一个类类型进行实例化操作的时候,实际上就是在内存中分配一段空间,用以创建该对象,并储存对象的一些值,如Name和Password等。对同一个类类型,如果没有特殊的限制,是可以同时创建多个对象的,这些对象被分配到不同的内存空间中,它们的类型虽然一样,却具有不同的对象状态,如内存地址、对象名、以及对象中各个成员的值等等。例如,我们可以同时创建两个User对象: 由于Name和Password属性是和对象紧密相关的,方法SignIn和SignOut的实现也调用了内部的Name和Password属性值,因此也和对象紧密相关,所以这些成员就不能被定义为静态成员。试想一下,如果把Name和Password属性均设置为静态属性,则设置其值时,只能采用如下形式: 显然,此时设置的Name和Password就与实例user无关,也就是说无论创建了多少个User实例,Name和Password都不属于这些实例,这显然和User类的意义相悖。对于方法SignIn和SignOut,也是同样的道理。当然我们也可以更改方法的定义,使得该方法可以被定义为static,如下所示: public class User
{ public static void SignIn(string userName, string password) { //代码略 } public static void SignOut(string userName, string password) { //代码略 } } 由于SignIn和SignOut方法需要调用的Name和Password值改为从方法参数中传入,此时这两个方法就与对象的状态没有任何关系。定义好的静态方法的调用方式略有不同: User user = new User();
user.Name = "bruce zhang"; user.Password = "password"; User.SignIn(user.Name, user.Password); User.SignIn(user.Name, user.Password);
那么为什么在LogManager类中,我将Logging方法均定义为静态方法呢?这是因为该方法与对象状态没有太大的关系,如果将方法的参数logFile和log定义为LogManager类的属性,从实际运用上也不合理,同时也会导致使用的不方便。最重要的是,一旦要调用非静态方法,不可避免的就需要创建实例对象。这会导致不必要的内存空间浪费。毕竟LogManager类型对于调用者而言,仅在于其Logging方法,而和对象的状态没有太大的关系,因此并不需要为调用这个方法专门去创建一个实例。这一点是和User类型是完全不同的。 在一个类类型的定义中,既可以允许静态成员,也可以允许非静态成员。然而在一个静态方法中,是不允许直接调用同一类型的非静态方法的,如下所示: public class Test
{ private void Foo1() { //代码略; } public static void Foo2() { Foo1(); //错误; } public void Foo3() { Foo1(); //正确; } }
public static void Foo2()
{ Test test = new Test(); testFoo1(); //正确; }
如果在类中定义了static的字段,有两种方式对其初始化。一是在定义时初始化字段,或者是在类型的构造器中为这些静态字段赋予初始值。例如: class ExplicitConstructor
{ private static string message; public ExplicitConstructor() { message = "Hello World"; } public static string Message { get { return message; } } } class ImplicitConstructor { private static string message = "Hello World"; public static string Message { get { return message; } } }
如果对于静态字段未设置值,.Net会给出警告,并根据类型的不同赋予不同的初始值。此外,static还可以和readonly结合起来使用,定义一个只读的静态变量。但是static不能应用到常量的定义中。 在C# 1.x中,static并不能用来修饰类类型,也就是说,我们不能定义一个静态类。然而对于一个类类型,如果其成员均为静态成员,则此时实例化该类是没有意义的。此时,我们常常将构造器设置为private,同时将其类设置为sealed(sealed表明该类不可继承,关于sealed会在后面介绍)。这样就可以避免对类的实例化操作,如前面定义的LogManager,即可以修改定义: public sealed class LogManager
{ private LogManager() {} public static void Logging(string logFile,string log) { using (StreamWriter logWriter = new StreamWriter(logFile,true)) { logWriter.WriteLine(log); } } }
由于静态类不支持实例化操作,因此在静态类的定义中,不允许再添加sealed或abstract关键字,也不允许继承某个类或被某个类继承,而类的成员中,也只能是静态成员,且不能定义构造器。由于不存在类的继承关系,因此,静态类成员中,也不允许有protected或protected internal作为访问限制修饰符。
参考文档:
C/S框架标准版和高级版有什么区别? CSFramework精简版和标准版有什么区别? C# C/S开发框架新增数据窗体 C# C/S结构快速开发框架标准版V2.2 - 视频介绍 什么是基于C#.Net平台的开发框架? 高级版不使用WebService,是不是与用标准版开发没有什么区别? C#.Net String类型Null与String.Empty有什么区别? C# 关键字const和static readonly 区别 C#语法中两个问号(??)的运算符是什么意思? 基础版V2.0与标准版V2.2有什么区别? C# CodeHighlighter生成的高亮着色HTML源码格式化 C# continue语句 开发框架使用.NET Reactor(加壳+代码混淆)与加密狗加密有什么区别 C# C/S架构软件自动升级程序Winform+多数据库(MySQL,MsSQL,Oracle) Winform轻量级框架和重量级框架有什么区别
其它资料:
什么是C/S结构? | C/S框架核心组成部分 | C/S框架-WebService部署图 | C/S框架-权限管理 | C/S结构系统框架 - 5.1旗舰版介绍 | C/S结构系统框架 - 功能介绍 | C/S结构系统框架 - 产品列表 | C/S结构系统框架 - 应用展示(图) | 三层体系架构详解 | C/S架构轻量级快速开发框架 | C/S框架网客户案例 | WebApi快速开发框架 | C/S框架代码生成器 | 用户授权注册软件系统 | 版本自动升级软件 | 数据库底层应用框架 | CSFramework.CMS内容管理系统 | |