zoukankan      html  css  js  c++  java
  • Chapter7 常量和字段

    1.1 常量

    常量(constant)是一个特殊的符号,它有一个从不变化的值,定义常量符号时,它的值必须能在编译时确定,确定之后,编译器将常量的值保存到程序集的元数据中。
    这意味着只能为编译器认定的基元类型定义常量,也可以是非基元类型,但必须是null。
    所以代码在引用一个常量符号时,不需要为常量分配任何内存,编译器会在元数据中提取常量值,嵌入的IL代码中。
    除此之外,不能获取常量的地址,也不能按引用的方式传递常量。
    这些限制意味着,常量没有很好的跨程序集版本特性 ,如果希望在运行时从一个程序集中提取另一个程序集中的值,那么不应该使用常量,而应该使用readonly字段

    下面举个例子
    将以下代码编译一个dll程序集(假定这个DLL程序集没有进行强命名)

    using System;
    
    namespace ClassLibrary
    {
        public sealed class SomeType
        {
            //注意:C#不允许为常量指定static关键字,因为常量总是隐式的static
            public const Int32 constValue = 50;
            //将类型和字段关联,因为static修饰的字段是类型状态的一部分,static关键字是必需的
            public static readonly Int32 readOnlyValue = 50;
        }
    }

    1.打开cmd->输入命令cd C:\Windows\Microsoft.NET\Framework\v4.0.30319 进入Framework4.0的安装目录(不同机器可能安装路径不一样,也可以使用vs自带的命令行提示工具)。
    2.将SomeType类型的代码源文件复制到上面目录,然后执行命令行:csc /target:library SomeType.cs,(csc.exe会默认reference MSCorLib.dll程序集)然后会生成一个SomeType.dll。
    3.接着用下面代码生成一个应用程序程序集:

    using System;
    
    namespace ConsoleApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("const value:" + ClassLibrary.SomeType.constValue);
                Console.WriteLine("readonly value:" + ClassLibrary.SomeType.readOnlyValue);
                Console.ReadLine();
            }
        }
    }

    4.将包含上面代码的源文件复制到同样的目录下,执行命令行:csc /out:Main.exe /target:exe /r:SomeType.dll Program.cs,然后生成一个Main.exe的应用程序
    运行Main.exe
    结果:const value:50
    readOnly value:50
    5.现在把SomeType中的值改为:

    public const Int32 constValue = 100;
    public static readonly Int32 readOnlyValue = 100;

    重新编译SomeType.dll,然后在运行Main.exe
    结果:const value:50
    readOnly value:100
    显然常量的值没有变,所以常量没有很好的跨程序集版本特性

    1.2字段

    字段(field)是一种数据成员,其中容纳了一个值类型的实例或者对一个引用类型的引用
    表格:
    CLR支持类型字段(静态字段)和实例字段(非静态)。
    对于静态字段,分配给它的内存是在类型对象中分配的,而类型对象是在类型加载到一个AppDomain时创建的,而AppDomain是在引用了该类型的方法首次进行JIT编译时加载的。
    对于实例字段,内存则是在构造类型的一个实例时分配的。

    CLR支持readonly字段和read/write字段,但大多是都是read/write字段(字段的值可多次改变),但是readonly字段只能在一个构造器方法中写入

    //这是一个静态readonly字段,在运行时对这个类型进行初始化,它的值会被计算并存储到内存中
    public static readonly Random s_random = new Random();
    //这是个静态read/write字段
    private static Int32 s_numberOfWrites=0;
    //这是一个实例readonly字段
    public readonly String Pathname = "Unitled";
    //这是个实例read/write字段
    private System.IO.FileStream m_fs;
    
    public SomeType(String pathname)
    {
    //改行修改只读字段pathname,由于代码在构造器中所以可以这样做
    this.Pathname = pathname;
    }
    
    public String DoSomething()
    {
    //该行读写静态read/write字段
    s_numberOfWrites = s_numberOfWrites + 1;
    //该行读取readonly实例字段
    return Pathname;
    }

    上面许多字段都是内联初始化,这只是C#语法的一种简化,实际上还是在构造器中初始化。

  • 相关阅读:
    Zstack中任务,事件,消息之间的关系
    Zigbee折腾之旅:(一)CC2530最小系统
    计算机中原码,反码,补码之间的关系
    Python3
    Python3
    Python3
    【基础】强软弱虚引用
    SpringBoot上传文件时MultipartFile报空问题解决方法
    Mockito中的@Mock和@Spy如何使用
    Vim 多行剪切、复制和删除
  • 原文地址:https://www.cnblogs.com/hailiang2013/p/2862545.html
Copyright © 2011-2022 走看看