常量
常量是值从不变化的符号。定义常量符号时,它的值必须能在编译时确定。确定后,编译器将常量值保存到程序集元数据中。这意味着只能定义编译器识别的基元类型的常量。在C#中,以下类型是基元类型,可用于定义常量 :Boolean,Char,Byte,SByte,Int16,UInt16,Int32,UInt32,Int64,UInt64,Single,Double,Decimal和String。然而,C#也允许定义非基元类型的常量变量(constant variable),前提是把值设为null
public sealed class SomeType {//SomeType不是基元类型,但C#允许 //值为null的这种类型的常量变量 public const SomeType Empty = null; }
编译器会将常量值嵌入引用它的位置。所以如果引用的是DLL中的常量,当这个DLL中的常量值变化时,应用程序要想获取到新值也得重新编译。如果希望在运行时从一个程序集中提取另一个程序集中的值,那么不应该使用常量,而应该使用 readonly 字段。
//转载 https://www.cnblogs.com/talentzemin/p/10944493.html var frameworkPath = RuntimeEnvironment.GetRuntimeDirectory(); var cscPath = Path.Combine(frameworkPath, "csc.exe");// C:\Windows\Microsoft.NET\Framework\v4.0.30319 Console.WriteLine(frameworkPath);// C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe Console.WriteLine(cscPath);
在CMD中输入: csc /target:library /out:Test.dll SomeType.cs 编译成DLL
字段
字段是一种数据成员,其中容纳了一个值类型的实例或者对一个引用类型的引用。
CLR 支持类型(静态)字段和实例(非静态)字段。如果是类型字段,容纳字段数据所需的动态内存是在类型对象中分配的,而类型对象是在类型加载到一个AppDomain时创建的。那么,什么时候类型加载到一个AppDomain中呢?这通常是在引用了该类型的任何方法首次进行JIT编译的时候。如果是实例字段,容纳字段数据所需的动态内存是在构造类型的实例时分配的。
字段修饰符 | ||
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的所有枚举类型。volatile字段将在 “基元线程同步构造” 讨论。 |
由于字段存储在动态内存中,所以它们的值在运行时才能获取。字段还解决了常量存在的版本控制问题。此外,字段可以是任何数据类型,不像常量那样仅仅局限于编译器内置的基元类型。
CLR 支持 readonly 字段和 read/write 字段。大多数字段都是 read/write 字段,意味着在代码执行过程中,字段值可多次改变。但 readonly 字段只能在构造器方法中写入。(构造器方法只能调用一次,即对象首次创建时)编译器和验证机制确保 readonly 字段不会被构造器以外的任何方法写入。注意,可利用反射来修改 readonly 字段。
//其他代码可以修改chars数组元素,但不能修改它的引用 public static readonly Char[] chars = new Char[] {'A', 'B', 'C'};