学习CLR via C#(第4版)(五) - 常量和字段

常量和字段

7.1常量

常量(constant)是一个特殊的值,它是一个从不变化的值。

在定义常量时,它的值必须在编译时确定。确定之后,编译器将常量的值保存到程序集的元数据中。这就意味着只能为编译器认定的基元类型定义常量。

C#是允许定义一个非基元类型的常量变量(constant variable),但这个值应设为null。

public sealed class SomeType {
    //SomeType不是基元类型,但C#允许定义
    //值为null的这种类型的一个常量变量
    public const SomeType Empty = null;    
}

由于常量的值从不变化,所以常量总是被视为类型定义的一部分。所以,常量是静态成员,而不是实例成员。定义常量将导致创建元数据。

代码引用一个常量符号时,编译器会在定义常量的程序集的元数据中查找该符号,提取常量的值,并将值嵌入生成的IL代码中。由于常量的值直接嵌入代码中,所以运行时不需要为常量额外分配内存。

除此之外,不能获取常量的地址,也不能以传递引用的方式传递常量。

基于上一条,假如A程序集只依赖于B程序集中的常量,那么编译后,即使删除B程序集,A程序集也不会受到影响,也是能找到B程序集中定义的常量值。

7.2字段

字段(field)是一种数据成员,其中容纳了一个值类型的实例或者对一个引用类型的引用。

下表总结了应用于字段的修饰符:

CLR术语C#术语说明
Staticstatic这种字段是类型状态的一部分,而不是对象状态的一部分
Instance默认这种字段与类型的一个实例关联,而不是与类型本身关联
InitOnlyreadOnly这种字段只能由一个构造器方法中的代码写入
Volatilevolatile看到访问这种字段的代码,编译器、CLR或硬件就不会执行一些"线程不安全"的优化措施

CLR支持类型(静态)字段和实例(非静态)字段。对于类型字段,用于容纳字段数据的动态内存是在类型对象中分配的,而类型对象是在类型加载到一个AppDomain时创建的。什么时候要将类型加载到一个AppDimain中呢?通常是在引用了该类型的任何方法首次进行JIT编译的时候。

对于实例字段,用于容纳字段数据的动态内存则是在构造类型的一个实例时分配的。

由于字段存储在动态内存中,所有它们的值在运行时才能获取。字段还解决了常量存在的版本控制的问题。此外,字段可以是任何数据类型。

CLR支持readonly字段和read/write字段。大多数字段是read/write字段,这意味着在代码执行过程中,字段可以多次改变。但是,readonly字段只能在一个构造器方法中写入(在这有人会有疑问,我可以直接定义readonly的值啊?比如private readonly int ss = 123;不必从构造器方法中写入?这问题,以后会提到)。注意,可以利用反射来修改readonly字段。

下面演示了如何定义一个与类型本身关联的readonly静态字段和读/写静态字段。另外还定义了read/wite静态字段,以及readonly和read/write实例字段。

public sealed class SomeType {
    // 这是一个静态readonly字段:在运行时对Random类进行初始化
    // 它的值会被计算并存储到内存中
    public static readonly Random s_random = new Random();
 
    // 这是一个静态read/write字段
    private static Int32 s_numberOfWrites = 0;
 
    // 这是一个实例readonly字段
    public readonly String Pathname = "Untitled";
 
    // 这是一个实例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#允许使用内联初始化语法来初始化类的常量、read/write字段和readonly字段。在后面会讲到,C#实际是在构造器中对字段进行初始化的,字段的内联初始化只是一种语法上的简化而已。另外,在C#中使用内联初始化,有一些性能问题需要考虑,这些以后会着重讲解。

注意,当某个字段是引用类型,并且该字段标记为readonly时,那么不可改变的引用,而非字段引用的值。

internal static class ReadOnlyReferences {
   public sealed class AType {
      // InvalidChars总是引用同一个数组对象
      public static readonly Char[] InvalidChars = new Char[] { 'A', 'B', 'C' };
   }
 
   public sealed class AnotherType {
      public static void M() {
         // 下面三行代码是合法的,可通过编译并运行
         // 修改InvalidChars数组中的字符
         AType.InvalidChars[0] = 'X';
         AType.InvalidChars[1] = 'Y';
         AType.InvalidChars[2] = 'Z';
 
         // 下一行代码是非法的,无法通过编译
         // 因为不能让InvalidChars 引用别的什么东西
         //AType.InvalidChars = new Char[] { 'X', 'Y', 'Z' };
      }
   }
}

const和readonly的区别是什么

const: const用来声明常量。

1)它的值必须在编译时确定;

2)编译器将常量的值保存在程序集的元数据中;

3)常量的值直接嵌入代码,运行时不需要为常量分配内存空间;

4)常量总被视为静态成员;

5)用const声明的类型必须是基元类型;

6)也允许定义一个非基元类型的常量变量(constant variable),但这个值应设为null

readonly: 用来声明只读字段。

1)只读字段只能在一个构造函数中写入;

2)可以用反射来修改readonly字段;

3)当只读字段为引用类型,不可改变的是引用,并非字段引用的对象。

举例:

using System;
class P
{
    static readonly int A=B*10;
    static readonly int B=10;
    public static void Main(string[] args)
    {
        Console.WriteLine("A is {0},B is {1} ",A,B);
    }
}

对于上述代码,输出结果是多少?很多人会认为是A is 100,B is 10吧!其实,正确的输出结果是A is 0,B is 10。

如果改成下面的话:

using System;
class P
{
    const int A=B*10;
    const int B=10;
    public static void Main(string[] args)
    {
        Console.WriteLine("A is {0},B is {1} ",A,B);
    }

}

对于上述代码,输出结果又是多少呢?难道是A is 0,B is 10?其实又错了,这次正确的输出结果是A is 100,B is 10

那么为什么是这样的呢?

其实在上面说了,const是静态常量,所以在编译的时候就将A与B的值确定下来了(即B变量时10,而A=B*10=10*10=100),那么Main函数中的输出当然是A is 100,B is 10啦。而static readonly则是动态常量,变量的值在编译期间不予以解析,所以开始都是默认值,像A与B都是int类型,故都是0。而在程序执行到A=B10;所以A=010=0,程序接着执行到B=10这句时候,才会真正的B的初值10赋给B。

静态字段和实例字段内存空间在什么时候分配?

静态字段的内存空间在类型对象中分配,类型对象是在类型加载到一个AppDomain时创建的,换言之,通常是在引用了该类型的任何方法首次进行JIT编译的时候;

实例字段的内存空间在构造类型的一个实例时分配。

CLR via C# 第4 英文PDFKristin, words cannot express how /feel about our life together. cherish our family and all our adventures. I'm filled each day with love for Aidan (age 9)and Grant (age 5), you both have been an inspira- tion to me and have taught me to play and have fun Watching the two of you grow up has been so rewarding and enjoyable for me. am lucky to be able to partake in your lives. love and ap preciate you more than you could ever know Contents at a glance Introduction PART I CLR BASICS CHAPTER 1 The clr's execution model CHAPTER 2 Building, Packaging, Deploying, and Administering Applications and Types 33 chaPTeR 3 Shared Assemblies and Strongly Named Assemblies 65 PART I DESIGNING TYPES CHAPTER 4 Type Fundamentals 91 CHAPTER 5 Primitive, Reference, and Value Types 111 CHAPTER 6 Type and Member Basics 151 CHAPTER 7 Constants and fields 175 chaPTer 8 Methods 181 chaPTer 9 Parameters 209 CHAPTER 10 Properties 227 CHAPTER 11 Events 249 CHAPTER 12 Generics 265 CHAPTER 13 Interfaces 295 PARTⅢ ESSENTIAL TYPES CHAPTER 14 Chars, Strings, and Working with Text 317 CHAPTER 15 Enumerated Types and Bit Flags 361 CHAPTER 16 Arrays 373 CHAPTER 17 Delegates 391 CHAPTER 18 Custom Attributes 421 CHAPTER 19 Nullable value Types 441 PART IV CORE FACILITIES CHAPTER 20 Exceptions and state management 451 CHAPTER 21 The Managed Heap and Garbage Collection 505 CHAPTER 22 CLR Hosting and AppDomains 553 CHAPTER 23 Assembly Loading and reflection 583 CHAPTER 24 Runtime serialization 611 CHAPTER 25 Interoperating with WinRT Components 643 PAR V THREADING ChaPTEr 26 Thread basics 669 CHAPTER 27 Compute-Bound Asynchronous Operations 691 CHAPTER 28 IyO-Bound Asynchronous Operations 727 CHAPTER 29 Primitive thread Synchronization Constructs 757 CHAPTER 30 Hybrid Thread Synchronization Constructs 789 Index 823 Contents at a glance Contents Introduction XX PART CLR BASICS Chapter 1 The Clrs Execution Model 3 Compiling Source Code into Managed Modules Combining managed modules into assemblies Loading the Common Language Runtime 8 Executing Your Assembly's Code 11 IL and∨ erification 16 Unsafe Code The Native Code generator tool: ngen. exe 19 The Framework Class Library 22 The Common Type System The Common Language Specification Interoperability with Unmanaged Code 30 Chapter 2 Building, Packaging, Deploying, and Administering Applications and Types 33 NET Framework Deployment Goals 34 Building Types into a Module 35 Response Fil 36 A Brief Look at metadata 38 What do you think of this book We want to hear from you Microsoft is interested in hearing your feedback so we can continually improve our books and learning resources for you. To participate in a brief online survey, please visit microsoft. com/learning/booksurvey Combining Modules to Form an Assembly 45 Adding Assemblies to a Project by Using the Visual Studio IDE.51 Using the assembly Linker Adding Resource Files to an Assembly 53 Assembly Version Resource Information .54 Version numbers ..58 Culture Simple Application Deployment(Privately deployed Assemblies)...60 Simple Administrative Control(Configuration) 62 Chapter 3 Shared Assemblies and Strongly Named Assemblies 65 Two Kinds of Assemblies, Two Kinds of Deployment 66 Giving an Assembly a Strong Name 67 The global Assembly Cache 72 Building an Assembly That References a Strongly Named Assembly..74 Strongly named assemblies are tamper-Resistant 75 Delayed Signing Privately Deploying Strongly Named Assemblies How the Runtime Resolves Type References 80 Advanced Administrative Control( Configuration) 83 Publisher Policy control 86 PART I DESIGNING TYPES Chapter 4 Type Fundamentals 91 All Types Are Derived from System Object .91 Casting Between Types 93 Casting with the C# is and as Operators Namespaces and assemblies 97 How Things relate at Run time .101 Chapter 5 Primitive, Reference, and Value Types 111 Programming Language Primitive Types 111 Checked and Unchecked Primitive Type Operations 115 Reference Types and value Types 118 Boxing and Unboxing Value Types 124 Changing Fields in a Boxed Value Type by Using Interfaces and Why You Shouldnt Do This) 136 Object Equality and Identity 139 Object hash Codes .142 The dynamic Primitive Type ......144 Chapter 6 Type and member Basics 151 The Different Kinds of Type Members .151 Type visibilit 154 Friend assemblies 154 Member accessibility .156 Static Classes ...158 Partial Classes, Structures, and Interfaces .159 Components, Polymorphism, and Versioning 160 How the CLR Calls Virtual Methods, Properties, and Events 162 Using Type Visibility and Member Accessibility Intelligently...166 Dealing with Virtual Methods When Versioning Types 16 Chapter 7 Constants and Fields 175 Constants 175 Fⅰe|ds ...177 Chapter 8 Methods 181 Instance Constructors and Classes(Reference Types) 181 Instance Constructors and Structures(Value Types) 184 Type Constructors 187 Contents x Operator Overload Methods 191 Operators and Programming Language Interoperability 193 Conversion Operator Methods 195 Extension method 198 Rules and guidelines ....,200 Extending Various Types with Extension Methods 201 The Extension Attribute 203 Partial Methods 204 Rules and guidelines 207 Chapter 9 Parameters 209 Optional and Named Parameters 209 Rules and guidelines 210 The defaultParameter value and optional Attributes 212 Implicitly Typed Local Variabl 212 Passing parameters by reference to a Method 214 Passing a variable Number of arguments to a Method 220 Parameter and Return Type Guidelines 223 Const-nes 224 Chapter 10 Properties 227 Parameterless Properties 227 Automatically Implemented Properties 231 Defining Properties Intelligently 232 Object and collection Initializers 235 Anonymous Type .237 The System. Tuple type 240 Parameterful Properties 242 The performance of calling property accessor Methods 247 Property Accessor Accessibility 248 Generic prop A roperty Access 248
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值