<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 原則2:偏愛 readonly 而不是 const **By D.S.Qiu** 尊重他人的勞動,**支持原創,轉載請注明[出處](/blog/1976703):[http://dsqiu.iteye.com](http://dsqiu.iteye.com)** C# 有兩種常量:編譯時常量和運行時常量。它們有不同的行為,不當使用會花費性能或出現錯誤。如果不得不選擇其中一個,寧可是一個慢一點但正確的程序,而不是一個快速但會出錯的程序。出于這個考慮,你應該更偏向于運行時常量而不是編譯時常量。編譯時常量會比編譯時常量稍微快點,但更不靈活。只有當性能是一個致命因素而且要求常量不隨版本發生改變時才會保留編譯時常量。 你可以使用 readonly 關鍵字聲明運行時常量。使用 const 關鍵字聲明編譯器常量: ``` // Compile time constant: public const int Millennium = 2000; // Runtime constant: public static readonly int ThisYear = 2004; ``` 上面的代碼可以出現類或結構體的作用域(scope)中。編譯時常量還可以在方法體中聲明。運行時常量不能在方法體重聲明。 編譯時常量和運行時常量訪問方式不同導致不同的行為。在目標代碼中編譯時常量會被替換成常量值。比如下面代碼: ``` // Compile time constant: public const int Millennium = 2000; // Runtime constant: public static readonly int ThisYear = 2004; ``` 會和下面寫法的編譯的 IL 代碼是一樣的: ``` if (myDateTime.Year == 2000) ``` 運行時常量的值是在運行時得到的。當你引用一個只讀(read-only)常量, IL 會引用一個 readonly 變量而不是直接使用值。 使用編譯時常量和運行時常量還有不同的限制。編譯時常量只能在基本類型(內建整數和浮點數類型),枚舉類型,或字符串。編譯時常量要求類能用有意義的常量賦值初始化。而只有基本類型才能在 IL 代碼中使用常量(literal values)來替換。不能使用使用 new 操作法初始化編譯時常量,即使它是一個值類型: ``` // Does not compile, use readonly instead: private const DateTime classCreation = new DateTime(2000, 1, 1, 0, 0, 0); ``` 編譯時常量只能使用與數字和字符串。只讀(Read-only)變量也是常量,即不能在構造函數完成之后再修改。但只讀變量是在運行時賦值。這會比編譯時常量更靈活。首先,運行時常量可以是任何類型。你必須在構造函數或者直接初始化。你可以讓 DateTime 結構體變為 readonly 值;但不能使用 const 創建 DateTime 值。 readonly 值可以是實例類型(instance)常量,讓一個類的實例存儲不同值。而編譯時常量則是被定義為 static 常量的。 只讀變量最重要的不同在于運行時才確定值。當你引用一個只讀變量, IL 會為你產生一個指向只讀變量的引用,而不是值。這種差異將對維護上產生深遠的影響。編譯時常量產生的 IL 代碼就跟直接使用數值變量時一樣的,即使是跨程序集:一個程序集的常量在另一個程序集還是被替換為數值。 編譯時常量和運行時常量的賦值方式會影響運行時的兼容性。假設你在程序集 Infrastructure 中同時定義了 const 和 readonly 域: ``` public class UsefulValues { public static readonly int StartValue = 5; public const int EndValue = 10; } ``` 在另外一個程序集,你引用這兩個值: ``` for (int i = UsefulValues.StartValue; i < UsefulValues.EndValue; i++) Console.WriteLine("value is {0}", i); ``` 如果你運行這個簡單的測試程序,很明顯你會得到下面的輸出: ``` Value is 5 Value is 6 ... Value is 9 ``` 一段時間后,你發布新版本的 Infrastructure 程序集并作下面的改動: ``` public class UsefulValues { public static readonly int StartValue = 105; public const int EndValue = 120; } ``` 你只發布程序集 Infrastructure 而沒有重新編譯全部應用程序。你希望得到下面的結果: ``` Value is 105 Value is 106 ... Value is 119 ``` 實際上,你不會得到任何輸出。循環條件開始于105,結束于10。 C# 編譯器用10替換應用程序集的 const 變量而不是指向存儲 EndValue 的引用。 StartValue 的情況趨勢截然不同。因為它被聲明為 readonly :在運行時確定值。因此,應用程序集能不用重新編譯就能充分利用新值;只要很簡單地按照更新版本的 Infrastructure 程序集就可以改變使用該變量的值。更新 public const 變量的值應該當做接口的變化。更新只讀常量的值只是實現的改變,兼容客戶端的二進制代碼。 另一方法,有時候某些值的確需要是編譯時常量。例如:考慮使用編譯時常量標記對象的序列化版本(查看原則27)。標記特定版本號的持久化值要使用編譯時常量,它們決不會發生改變。但當前的版本號應該是一個運行時常量,隨著版本不同而改變。 ``` private const int Version1_0 = 0x0100; private const int Version1_1 = 0x0101; private const int Version1_2 = 0x0102; // major release: private const int Version2_0 = 0x0200; // check for the current version: private static readonly int CurrentVersion = Version2_0; ``` 你會使用運行時常量存儲每個文件的當前版本號: ``` // Read from persistent storage, check // stored version against compile-time constant: protected MyType(SerializationInfo info, StreamingContext cntxt) { int storedVersion = info.GetInt32("VERSION"); switch (storedVersion) { case Version2_0: readVersion2(info, cntxt); break; case Version1_1: readVersion1Dot1(info, cntxt); break; // etc. } } ``` ``` // Write the current version: [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)] void ISerializable.GetObjectData(SerializationInfo inf, StreamingContext cxt) { // use runtime constant for current version: inf.AddValue("VERSION", CurrentVersion); // write remaining elements... } ``` 相比 readonly ,使用 const 最后的一個優勢就是性能:已知的常量值會比使用變量訪問的 readonly 變量產生稍微高效的代碼。然而,性能上甚微的收效和靈活性的減小應該做一個很好的權衡。放棄靈活性之前一定要剖析性能差異。可選參數的默認值會在調用時會像編譯時變量(聲明為 const 的變量)一樣被替換成默認值。和使用 readonly 和 const 變量一樣,你要非常認真對待可選參數值的不同。(查看原則10。) 當你使用命名(named)參數和可選(optial)參數時,你會遇到和使用運行時常量和編譯時常量一樣的權衡。 當在編譯時期必須要獲得變量的值時必須使用 const :特性(attribute)參數和枚舉定義,以及當你定義一個不隨版本的變化而變化的值得罕見的時候。無論如何,更偏愛于只讀常量的更強的靈活性。 小結: 第二節字數相對少些,所以今天雖然頸椎有點不舒服(千萬不要有事呀,我還沒有瘋夠),根據以前的節奏(時間還早),還可以干點別的,或者躲進被窩理順事情,每天給自己思考的事件太少了,沒有思考,積淀就會來的慢,這個跟前面強調的不同哈。 歡迎各種不爽,各種噴,寫這個純屬個人愛好,秉持”分享“之德! 有關本書的其他章節翻譯請[點擊查看](/category/297763),轉載請注明出處,尊重原創! 如果您對D.S.Qiu有任何建議或意見可以在文章后面評論,或者發郵件(gd.s.qiu@gmail.com)交流,您的鼓勵和支持是我前進的動力,希望能有更多更好的分享。 轉載請在**文首**注明出處:[http://dsqiu.iteye.com/blog/1976703](/blog/1976703) 更多精彩請關注D.S.Qiu的 博客 和微博(ID:靜水逐風)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看