首页 > 编程语言 >《NET CLR via C#》---第七章(常量,读/写字段,可读字段)

《NET CLR via C#》---第七章(常量,读/写字段,可读字段)

时间:2024-08-14 20:05:28浏览次数:6  
标签:via 常量 C# MAX 编译器 --- 字段 类型 public

常量

常量是值从不变化的符号。定义常量符号时,它的值必须能在编译时确定。确定后,编译器将常量值保存到程序集元数据中。这意味着只能定义编译器识别的基元类型的常量。在C#中,可用于定义常量:Boolean,Char,Byte,SByte,Int16,UInt16,Int32,UInt32,Int64,UInt64,Single,Double,Decimal,String。C#也允许定义非基元的常量变量,前提是把值设为null:

public class Program
{
    public const Program program = null;
}

代码引用常量符号时,编译器在定义常量的程序集的元数据中查找该符号,提取常量的值,将值嵌入生成的IL代码中。由于常量的值直接嵌入生成的IL代码中,所以在运行时不需要为常量分配任何内存。除此之外,不能获取常量的地址,也不能以传引用的方式传递常量。

这也意味着没法做到很好的版本控制。例如我们首先编译一个dll,这个程序集内存在一个常量:

public sealed class SomeLibraryType 
{
    public const int MAX = 50;
}

接下来用以下代码生成一个应用程序程序集:

public class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(SomeLibraryType.MAX);
    }
}

编译器在生成代码时,会注意到MAX是值为50的常量符号,所以会将int值50嵌入应用程序的IL代码。事实上,在生成应用程序程序集后,运行根本不会加载DLL程序集,可以把它从磁盘上删除。
image
这个例子清楚的展示了版本控制问题。如果开发人员将常量MAX更改为1000,且只是重新生成dll,那么应用程序程序集不会有任何影响,依然输出50。想要输出新值,则需要重新编译。

字段

字段是一种数据类型,其中容纳了一个值类型的实例或者对一个引用类型的引用。CLR支持类型(静态)字段和实例(静态)字段。如果是类型字段,容纳字段数据所需的动态内存是在类型对象中分配的,而类型对象是在类型加载到一个AppDomain时创建的。将类型加载到一个AppDomain的时机通常是在引用了该类型的任何方法首次进行JIT编译的时候。如果是实例字段,容纳字段数据所需的动态内存是在构造类型的实例时分配的。

CLR支持readonly字段和read/write字段。大多数字段都是read/write字段,意味着在代码执行过程中,字段值可以多次改变。但readonly字段只能在构造器方法中写入(构造器方法只会在对象生成时,调用一次)。编译器和验证机制确保readonly字段不会被构造器以外的任何方法写入。不过我们仍然可以通过反射的方式修改readonly字段。

修改下之前的代码,举个例子,将SomeLibraryType类型更改如下,重新生成dll:

public sealed class SomeLibraryType 
{
    public static readonly int MAX = 50;
}

然后我们重新编译应用程序程序集,会输出50。我们将SomeLibraryType.MAX改为1000,然后重新编译dll,会发现能够输出1000了。使用ildasm.exe查看下IL代码,可以看到,它会去对应程序集中找MAX值:
image

以下表格稍微介绍一下字段修饰符

CLR术语 C#术语 说明
Static static 这种字段是类型状态的一部分,而不是对象状态的一部分
Instance 默认 这种字段与类型的一个实例关联,而不是与类型本身关联
InitOnly readonly 这种字段只能由一个构造器方法中的代码写入
Volatile volatile 编译器,CLR和硬件不会对访问这种字段的代码执行“线程不安全”的优化措施。只有以下类型能标记为volatile:所有引用类型,Single,Boolean,Byte,SByte,Int16,UInt16,Int32,UInt32,Char,以及基础类型为Byte,SByte,Int16,UInt16,Int32,UInt32的所有枚举类型

标签:via,常量,C#,MAX,编译器,---,字段,类型,public
From: https://www.cnblogs.com/chenxiayun/p/18358910

相关文章

  • 《NET CLR via C#》---第六章(类型成员,类型的可访问性,友元程序集,分部类型,CLR调用方法指
    类型成员类型可以定义0个或者多个以下种类的成员。成员描述常量常量是指出数据值恒定不变的符号。这种符号使代码更易阅读和维护。常量总与类型关联,不与类型的实例关联。常量总与类型关联,不与类型的实例关联字段字段表示只读或可读/可写的数据值。字段可以是静态......
  • 腾讯微服务框架(TSF)-令牌桶限流的实现方式
    1为什么需要限流限流,也称流量控制。是指系统在面临高并发,或者大流量请求的情况下,限制新的请求对系统的访问,从而保证系统的稳定性。限流会导致部分用户请求处理不及时或者被拒,这就影响了用户体验。所以一般需要在系统稳定和用户体验之间平衡一下。举个生活的例子:比如我们的交......
  • 【C++】————C++11
                                 作者主页:   作者主页                           本篇博客专栏:C++                ......
  • 按钮(Buttons)-Qt-思维导图-学习笔记
    按钮(Buttons)按钮在Qt中的重要性按钮是Qt中最常用的控件之一通过点击按钮,可以响应事件,实现人机交互效果按钮在嵌入式系统和PC端的界面交互中都是不可或缺的Qt内置的六种按钮部件QPushButton:下压按钮用法示例项目创建与设置项目名称:创建一个名为04_qp......
  • SO-Net: Self-Organizing Network for Point Cloud Analysis
    Abstract本文提出了SO-Net,是一种创新的深度学习架构,为处理无序点云数据设计。SO-Net利用自组织映射(SOM)技术来捕捉点云的空间分布,并实现排列不变的特征提取。这种分层特征提取方法能够从局部到全局提取特征,还能够通过点到节点的k最近邻搜索系统地调整网络的receptivefield,从......
  • Android10.0 最近任务Recents功能分析
    在Android10.0上,Recents功能分布在SystemUI和Launcher3里面集成.一.初始化跟Android8.1类似,先看初始化入口:1.Recents.javaRecents继承SystemUI,进程启动后会在Dependency里面通过@Inject进行初始化,然后在SystemUIService里面调用SystemUIApplication的startServicesIfNee......
  • SciPy从入门到放弃
    目录SciPy简介拟合与优化模块求最小值曲线拟合线性代数模块统计模块直方图和概率密度函数统计检验SciPy简介SciPy是一种以NumPy为基础,用于数学、工程及许多其他的科学任务的科学计算包,其使用的基本数据结构是由NumPy模块提供的多维数组,因此Numpy和SciPy协同使用可以更加高效地解......
  • 在虚拟机CentOS中安装jdk
    公众号本文地址:在虚拟机CentOS中安装jdk本文主要是记录在CentOS中安装新的JDK的过程。在虚拟机的centos中安装Jdk主要分为三步,第一步上传jdk文件到centos中,第二步解压jdk文件,第三步配置环境变量。一般在安装完CentOS后系统是有jdk的,但是默认为openjdk1.8.0版本由于开发需要使......
  • 在虚拟机CentOS中安装docker
    公众号本文地址:在虚拟机CentOS中安装Docker1、关闭防火墙docker需要用到网络,所以需要关闭防火墙。进入管理员模式获得权限后进行关闭。su关闭防火墙:systemctldisablefirewalldsystemctlstopfirewalld2、禁用selinux(1)进入配置文件vim/etc/selinux/configvim/etc/......
  • D43 2-SAT+前缀优化 P6378 [PA2010] Riddle
    视频链接: P6378[PA2010]Riddle-洛谷|计算机科学教育新生态(luogu.com.cn)//2-SAT+前缀优化O(n+m)#include<iostream>#include<cstring>#include<algorithm>usingnamespacestd;#definex0(x)x//点#definex1(x)x+n//反点#definep0(x)x+2*n......