Programming C#.Classes and Objects.只读字段
只讀字段
當字段聲明中含有?readonly?修飾符時,該聲明所引入的字段為只讀字段。給只讀字段的直接賦值只能作為聲明的組成部分出現,或在同一類中的實例構造函數或靜態構造函數中出現。(在這些上下文中,只讀字段可以被多次賦值。)準確地說,只在下列上下文中允許對?readonly?字段進行直接賦值:
- 在用于引入該字段的變量聲明符中(通過添加一個變量初始值設定項)。
- 對于實例字段,在包含字段聲明的類的實例構造函數中;對于靜態字段,在包含字段聲明的類的靜態構造函數中。也只有在這些上下文中,將?readonly?字段作為?out?或?ref?參數傳遞才有效。
在其他任何上下文中,試圖對?readonly?字段進行賦值或將它作為?out?或?ref?參數傳遞都會導致一個編譯時錯誤。
?
C#常量數據與只讀字段
常量數據
C#提供了const關鍵字來定義常量,如果我們要為應用程序定義邏輯上和某個類或結構相關的一組已知值的話,就非常有用。
假如我們創建一個MyMathClass的工具類,且需要定義一個PI值(假如是3.14),如果不希望別的開發者改變PI值,可以使用如下常量定義PI值:
1 class MyMathClass 2 { 3 //定義為常量數據 4 public const double PI=3.14; 5 } 6 class Program 7 { 8 public static void Main(string[] args) 9 { 10 //注意:因為常量數據是隱式靜態的,所以只能直接在類級別上調用(MyMathClass.PI)。 11 Console.WriteLine("PI值是:{0}",MyMathClass.PI); 12 13 //錯誤!常量數據不能被修改。 14 MyMathClass.PI=3.15; 15 Console.ReadLine(); 16 } 17 }注意:定義常量時必須為常量指定初始值,常量一旦定義就不能修改了。
1 class MyMathClass 2 { 3 //嘗試再構造函數中給常量賦值 4 public const double PI; 5 public MyMathClass() 6 { 7 //錯誤! 8 PI=3.14; 9 } 10 }在編譯時必須知道常量的值!
只讀字段
和常量密切聯系的概念是只讀字段(不要和只讀屬性混淆哦,只讀屬性指只有get塊的屬性)。和常量相似,只讀字段不能在賦值后改變。然而,和常量不同,賦值給只讀字段可以在運行時決定。因此在構造函數作用域范圍內給只讀字段賦值是合法的(其他地方不行!)。
1 class MyMathClass 2 { 3 //可以構造函數中為只讀字段賦值,其他地方不行! 4 public readonly double PI; 5 public MyMathClass() 6 { 7 PI=3.14; 8 } 9 public void ChangePI() 10 { 11 //錯誤! 12 PI=3.14; 13 } 14 }另:只讀字段不是隱式靜態的,要定義靜態只讀字段就需要使用static關鍵字了。
問題:請敘述const與readonly的區別。
?? ?const 關鍵字用于修改字段或局部變量的聲明。它指定字段或局部變量的值不能被修改。常數聲明引入給定類型的一個或多個常數,開心哦。const數據成員的聲明式必須包含初值,且初值必須是一個常量表達式。因為它是在編譯時就需要完全評估。const成員可以使用另一個const成員來初始化,前提是兩者之間沒有循環依賴。readonly在運行期評估賦值,使我們得以在確保“只讀訪問”的前提下,把object的初始化動作推遲到運行期進行。
?? ?readonly 關鍵字與 const 關鍵字不同: const 字段只能在該字段的聲明中初始化。readonly 字段可以在聲明或構造函數中初始化。因此,根據所使用的構造函數,readonly 字段可能具有不同的值。另外,const 字段是編譯時常數,而 readonly 字段可用于運行時常數。readonly 只能在聲明時或者構造函數里面初始化。
readonly的作用就是:一些變量,不允許別人修改,但是在聲明的時候還不能對其賦值,所以不能用const常亮。這時可以用readonly關鍵字,在類的構造函數中對這些變量賦值。
枚舉與常量需要注意的一個問題
.net中枚舉其實就是數值型的常量,與const類似。當我們在代碼中使用枚舉代表的數值或者常量時,編譯器其實是將該值直接寫過來,而不會在運行的時候去讀取該值。下面是一個例子:
我們想建立一個類庫項目,名稱叫ClassLibrary1,再建立一個控制臺項目,名稱叫ConsoleApplication2,結構如下:
ClassLibrary1項目中Class1中的代碼是:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace ClassLibrary1 7 { 8 public class MyClass 9 { 10 public static string str1 = "str1"; 11 public const string str2 = "str2"; 12 } 13 14 public enum MyEnum 15 { 16 One = 1, 17 Two = 2, 18 Three = 3 19 } 20 }定義了一個枚舉以及一個靜態字段、一個常量字段。
ConsoleApplication2項目引用A項目,代碼如下:
1 using System; 2 using ClassLibrary1; 3 4 class Program 5 { 6 public static void Main(string[] args) 7 { 8 Console.WriteLine((int)MyEnum.One); 9 Console.WriteLine(MyEnum.One.ToString()); 10 11 Console.WriteLine(MyClass.str1); 12 Console.WriteLine(MyClass.str2); 13 14 Console.ReadKey(); 15 } 16 }我們來看看Program類用Reflector工具反編譯后的樣子:
public class MyClass {// Fieldspublic static string str1;public const string str2 = "str2";// Methodsstatic MyClass();public MyClass(); }注意:這里自動的添加了兩個構造函數,一個靜態一個非靜態。 1 public static void Main(string[] args) 2 { 3 Console.WriteLine(1); 4 Console.WriteLine(MyEnum.One.ToString()); 5 Console.WriteLine(MyClass.str1); 6 Console.WriteLine("str2"); 7 Console.ReadKey(); 8 }編譯器將(int)MyEnum.One的值與常量字段str2直接硬編碼寫到代碼中,而不是在運行期再去讀取。
這樣處理的后果是:如果你修改了A項目中的枚舉的排列順序或者枚舉對應的值(或者改變了常量字段str2的值),比如將MyEnum.One的值2,同時不重新編譯Test項目,那樣運行結果還是不會變的。
?
轉載于:https://www.cnblogs.com/stemon/p/4087881.html
總結
以上是生活随笔為你收集整理的Programming C#.Classes and Objects.只读字段的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Axure 8.0/9.0 注册码 激活
- 下一篇: ibatis的简介与初步搭建应用