热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C#中const、static、readonly的区别

一、const与readonly介绍①【const】其修饰的变量只能在声明时赋值进行初始化。②【Readonly】是只读变量,可以在声明或构造函数中初始化。③小

一、 const与readonly介绍

①【const其修饰的变量只能在声明时赋值进行初始化

②【Readonly是只读变量,可以在声明或构造函数中初始化。

③小结:

《1》根据所使用的构造函数,readonly 字段可能具有不同的值。

《2》对于每一次编译后的结果,const的值是固定的,而readonly的值是可以在运行的时候才确定值的

④const(常量)与readonly的10个区别

⑤const示例:

常量字段没有分配内存;当你定义一个常量字段时,它的值必须在声明本身的时候被分配,之后我们不能改变它的值

Public class Program{const int num = 10; //全局变量字段static void Main(string[] args){const int numberPerson = 10//正确的 //局部变量const int numTeacher = num; //正确的const int methodValue = GetTestValue(); // 错误的} public static int GetTestValue(){const int localValue=10;return 10;}}

[ const int methodValue = GetTestValue(); // 错误的]是因为声明了一个变量(methodValue)的常量,试图在运行时使用GetTestValue()方法运行时的返回值,这将不会执行,因为常量变量值必须在声明本身的时候被分配,不能动态改变。

注意:作为默认静态的常量变量,我们无法从类的实例中访问它。所以我们不能将const值作为ref或out参数传递。

⑥readonly示例:

  readonly字段属于类的对象,可以在声明或构造函数中初始化。

public class ReadonlyConstant{public const int numberOfDays = 7; //字段public readonly double PI=3.14; //内联初始化public readonly int znumber;public readonly List readonlyList;public ReadonlyConstant(){znumber= 50;//构造函数初始化 }public ReadonlyConstant(int x){znumber=100;}public NormalMethod(){//readonly int i=0; 这是错误的}}
二、const 与 static介绍

①【static】定义的是静态变量,可以在外部改变它的值。

②  const 和 static 不能在一起用。

③二者本质的差别:

《1》const的值是在编译期间确定的,因此只能在声明时通过常量表达式指定其值。

《2》而static,readonly是在运行时计算出其值的,所以还能通过静态构造函数来赋值。

public class TestConstAndStatic{public const int numberOfDays = 7; //常量字段public static double PI=3.14; //静态字段public const static int a=0; //错误,const与static不能同时使用public TestConstAndStatic(){numberOfDays=5;//错误(const变量只能在声明的时候指定值) PI=3.141592657;//正确,可以在运行时动态指定}}

 

④static在多线程中的使用

《1》类的成员分为两类,静态成员(静态成员属于类)实例成员(实例成员则属于对象,即类的实例)

《2》简单讨论一下在一个类中使用静态字段(static field)静态方法(static method)是否会有线程安全问题。 

    1、我们在知道, 静态字段(static field)和静态方法(static method)的调用是通过类来调用静态方法不对特定的实例操作,只能访问静态成员。实例方法可对特定的实例操作,既能访问静态成员,也能访问实例成员。

    2、那么,在多线程中使用静态方法是否有线程安全问题?要看静态方法是引起线程安全问题要看在静态方法中是否使用了静态成员。

    3、因为,在多线程中使用同一个静态方法时,每个线程使用各自的实例字段(instance field)的副本,而共享一个静态字段(static field)。所以说,如果该静态方法不去操作一个静态成员,只在方法内部使用实例字段(instance field),不会引起安全性问题。但是,如果该静态方法操作了一个静态字段,则需要静态方法中采用互斥访问的方式进行安全处理;如下示例所示。

public class Test
{public static String hello(String str){String tmp = "";tmp = tmp + str;return tmp;}
}

这个Tesst类中的静态hello方法没有多线程安全问题!!! 

⑤对于那些本质上应该是常量,不过却无法使用const来声明的地方,能使用static readonly。例如C#规范中给出的例子:

public class Color
{public static readonly Color Black = new Color(0, 0, 0);public static readonly Color White = new Color(255, 255, 255);public static readonly Color Red = new Color(255, 0, 0);public static readonly Color Green = new Color(0, 255, 0);public static readonly Color Blue = new Color(0, 0, 255);private byte red, green, blue;public Color(byte r, byte g, byte b){red = r;green = g;blue = b;}
}

三、static readonly介绍

 ①我们仅在【声明】或【静态构造函数】时分配static readonly字段。

  由于readonly字段值不同,取决于使用的构造函数。为了使它成为类成员(静态成员)和唯一的类,我们将在变量之前添加static关键字,如下所示。

public class TestReadonlyStatic
{public static readonly string x = "Hi";public static readonly string y;public TestReadonlyStatic(){//y = "Hello"; 这是错误的}static TestReadonlyStatic(){y = "Hello";}
}

②C#中readonly和static readonly字段之间的主要区别

 

四、何时使用const、readonly、static readonly

①当值是绝对不变的时候,使用【const】,这在时间上是不变的。例如一周的天数是7。这始终是常数。

②我们想要对类(或对象)的不同实例使用不同的常量值,请使用【readonly】。

③在项目的配置文件中配置的项目中(类构造时初始化的常量),可能会变动的常量(比如PI),请使用【static readonly】

注意:而在使用static readonly时,要避免dll版本问题;由于在IL内嵌有不变的值,我们可以使用常量修饰符来获得性能上的好处。

 

 

 

 

 

 

 

 

 


推荐阅读
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 本文介绍了Java中Currency类的getInstance()方法,该方法用于检索给定货币代码的该货币的实例。文章详细解释了方法的语法、参数、返回值和异常,并提供了一个示例程序来说明该方法的工作原理。 ... [详细]
  • 本文介绍了GTK+中的GObject对象系统,该系统是基于GLib和C语言完成的面向对象的框架,提供了灵活、可扩展且易于映射到其他语言的特性。其中最重要的是GType,它是GLib运行时类型认证和管理系统的基础,通过注册和管理基本数据类型、用户定义对象和界面类型来实现对象的继承。文章详细解释了GObject系统中对象的三个部分:唯一的ID标识、类结构和实例结构。 ... [详细]
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文介绍了RxJava在Android开发中的广泛应用以及其在事件总线(Event Bus)实现中的使用方法。RxJava是一种基于观察者模式的异步java库,可以提高开发效率、降低维护成本。通过RxJava,开发者可以实现事件的异步处理和链式操作。对于已经具备RxJava基础的开发者来说,本文将详细介绍如何利用RxJava实现事件总线,并提供了使用建议。 ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
  • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
  • 在C#中,使用关键字abstract来定义抽象类和抽象方法。抽象类是一种不能被实例化的类,它只提供部分实现,但可以被其他类继承并创建实例。抽象类可以用于类、方法、属性、索引器和事件。在一个类声明中使用abstract表示该类倾向于作为其他类的基类成员被标识为抽象,或者被包含在一个抽象类中,必须由其派生类实现。本文介绍了C#中抽象类和抽象方法的基础知识,并提供了一个示例代码。 ... [详细]
author-avatar
让爱自由2009
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有