专栏首页喵叔's 专栏巧用 readonly与 const

巧用 readonly与 const

c# 中的常量有两种,分别是编译期常量和运行期常量。通过名字我们就可以看出来它俩在行为上是不同的。在开发中如果这两种常量选择的不合适,就会影响到程序的开发工作以及程序的性能。下面我们先来看一下运行期常量和编译期常量的定义方法。

零、定义

运行期常量我们使用 readonly 来定义,而编译器常量我们使用 const 来定义。

// 运行期常量
public static readonly string name = "张三" ;
//编译期常量
public const int age = 20 ;

一、运行期常量和编译期常量

1.编译期常量 编译期常量可以使程序运行速度变得快一些,但是它没有运行期常量灵活,一般我们会在特别关注程序性能,并且常量取值不会随版本的变化而变化的情况下才会使用到它。这种常量与直接使用字面量的写法在编译为 MSIL 后的结果是一样的。例如 if( userAge == age )等价于 if( userAge == 20 )。 这里有几点很重要的需要注意:

  • 编译期常量只能用内置的整数、浮点数、枚举、字符串或 null 来进行初始化和赋值,在生成 MSIL 的过程中只有这些原始类型的编译期常量才会被替换成字面量;
  • 编译期常量可以在方法内部声明;
  • 编译期常量是静态常量;
  • 在另一个程序集中调用静态常量会导致不兼容问题(这个问题将在案例小节中讲解)。

2.运行期常量 在开发的大部分情况下我们使用的是运行期常量,这种常量灵活性强,几乎可以支持所有的类型。它不仅可以在声明的时候直接初始化,也可以在构造器中初始化。运行期常量所生成的 MSIL 会通过引用的方式来使用这个常量。 同样这里有几点需要注意:

  • 运行期常量可以用来声明实例级别的常量,给同一个实例设定不同的常量值;
  • 运行期常量是在程序运行时才会被解析。

二、案例

下面我们来看一个案例:

namespace readonly_and_const
{
    public class main
    {
        public static readonly string name = "张三";
        public const int age = 20;
    }
}

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(readonly_and_const.main.age);
            Console.WriteLine(readonly_and_const.main.name);
            Console.Read();
        }
    }
}

上述代码中我们创建了两个程序集,Test 程序集引用了 readonly_and_const 程序集。我们先行一下代码,来看一下运行结果:

下面我们将程序集 readonly_and_const 中的 age 和 name 都进行修改并运行:

namespace readonly_and_const
{
    public class main
    {
        public static readonly string name = "jack";
        public const int age = 25;
    }
}

运行结果如下:

我们从运行结果可以看到,name 的值已经改变,但是 age 的值没有改变,这是因为在编译 Test 程序集时编译器直接写入了 20 这个字面量,而不是去引用放置 age 的那个空间。但是 name 因为时运行期常量,因此会在运行时去应用放置了 name 的那个空间,因此输出了正确的值。解决这个问题有两种方法,一种是将 age 修改为运行期常量,另一种是重新编译 Test 程序集。具体应该使用哪个方法解决,应该视程序而定。

Tip:修改访问级别为 public 的 const 常量时调用它的程序集必须重新编译,因为这种修改相当于修改接口。但是修改 public 级别的 readonly 常量相当于修改细节实现,

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • SignalR 2.x入门(一):SignalR简单例子

    创建空Asp.Net Web项目,在程序包管理器控制台中输入如下命令,安装SignalR:

    喵叔
  • docker学习笔记-简介

    喵叔
  • 控制反转_依赖注入简明教程

    在面向对象中IOC是一个重要的设计思想。这篇文章将带领大家快速掌握控制反转和依赖注入。

    喵叔
  • C语言中的5种常量以及它们的不同之处

    你有没有想过,什么是C常量?为什么它们是编程世界的重要组成部分?我们已经得到了你所有问题的答案。C编程中的常量只是一些固定的值,在整个程序运行过程中都不能改变。...

    AI研习社
  • 触摸Java常量池

    java常量池是一个经久不衰的话题,也是面试官的最爱,题目花样百出,这次好好总结一下。

    Java团长
  • JVM内存模型之运行时常量池

    运行时常量池 jdk7之前属于方法区的一部分,jdk8之后属于Metaspace,在heap中。 运行时常量池俗称常量池,主要用于存放编译期生成的各种字...

    shengjk1
  • 面试题系列第5篇:JDK的运行时常量池、字符串常量池、静态常量池,还傻傻分不清?

    【番外篇】本篇核心:JDK各个版本中JDK的运行时常量池、字符串常量池、静态常量池的功能及存储位置。

    程序新视界
  • Java开发编程规范: 2.常量定义

         1)跨应用共享常量:放置在二方库中,通常是 client.jar 中的 constant 目录下。

    花狗Fdog
  • PHP-常量

    cwl_java
  • C/C++文字常量与常变量

    在C/C++编程时,经常遇到以下几个概念:常量、文字常量、字面常量、符号常量、字符常量、常变量、字符串常量等,网上的资料描述的不尽相同,弄得大家云里雾里。本文将...

    Dabelv

扫码关注云+社区

领取腾讯云代金券