首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

[你必須知道的.NET]第二十二回:字串駐留(上)—帶著問題思考

     編輯:關於.NET

走鋼絲的人,在刺激中體驗快感。帶著問題思考,在問題上迸發火花。

或許給問題以答案,或許給答案以問題,你可能永遠無法看清全部,但總能從一點突破許多。事實的關鍵在於面對問題,我該如何思考?

String Interning(字串駐留)就是這樣一個值得思考的話題。帶著問題思考,我們至少要理清:

  • 什麼是 string?
  • 什麼是字串駐留?
  • 字串駐留的運行機制與執行過程?
  • 字串駐留的其他問題?

1. 帶著問題出發

本文源自朋友 KiMoGiGi 的來函探討。首先從 8 個測試開始,希望讀者沿著示例思考答案:

測試 1

static void Main()
{
    string s1 = "abc";
    Console.WriteLine(string.IsInterned(s1) ?? "null");
}

測試 2

static void Main()
{
    string s1 = "ab";
    s1 += "c";
    Console.WriteLine(string.IsInterned(s1) ?? "null");
}

測試 3

static void Main()
{
    string s1 = "abc";
    string s2 = "ab";
    s2 += "c";
    string s3 = "ab";
    Console.WriteLine(string.IsInterned(s1) ?? "null");
    Console.WriteLine(string.IsInterned(s2) ?? "null");
    Console.WriteLine(string.IsInterned(s3) ?? "null");
}

測試 4

static void Main()
{
    string s1 = "abc";
    string s2 = "ab";
    string s3 = s2 + "c";
    Console.WriteLine(string.IsInterned(s3) ?? "null");
}

測試 5

static void Main()
{
    string s2 = "ab";
    s2 += "c";
    Console.WriteLine(string.IsInterned(s2) ?? "null");
    string s1 = "abc";
}

測試 6

static void Main()
{
    string s2 = "ab";
    s2 += "c";
    Console.WriteLine(string.IsInterned(s2) ?? "null");
    string s1 = GetStr();
}
private static string GetStr() { return "abc"; }

測試 7

public const string s1 = "abc";
static void Main()
{
    string s2 = "ab";
    s2 += "c";
    Console.WriteLine(string.IsInterned(s2) ?? "null");
}

測試 8

public static string s1 = "abc";
static void Main()
{
    string s2 = "ab";
    s2 += "c";
    Console.WriteLine(string.IsInterned(s2) ?? "null");
}

2. 欲求思考,從基本開始

什麼是 string

本質上,string 就是一連串有順序的字元集合,也就是 char[]。在 .NET 中 string 首次具有類別概念,符合「一切皆物件」的大一統格局。打開 string 的反組譯程式碼可直擊其本質:

[Serializable, ComVisible(true)]
public sealed class String : IComparable, ICloneable, IConvertible, 
    IComparable<string>, IEnumerable<char>, IEnumerable, IEquatable<string>
{
}

string 的基本特性包括:

  • 參考型別
  • 字串恆等性
  • 字串駐留性(本文研究重點)
  • 密封性(sealed 關鍵字),為實現恆等性與駐留機制提供基礎保證

什麼是字串駐留

MSDN 說明:CLR 透過維護一個表(稱為駐留池)來存放字串,該表包含程式中以程式設計方式宣告或建立的每個唯一字串的一個參考。因此,具有特定值的字串執行個體在系統中只有一個。

基本原理:

  1. CLR 維護類似雜湊表的內部結構,統一管理字串。
  2. JIT 編譯時,CLR 先查找雜湊表;若無匹配記錄,則在受控堆疊建立新 string 實例,並為雜湊表新增鍵值對;下次查找相同字串時,直接返回該記錄值。
  3. 透過此機制,有效實現字串池管理,節省大量記憶體空間。

注意:動態建立的字串不執行字串駐留機制,例如:

string s1 = "abc";
string s2 = "ab";
string s3 = s2 + "c";
Console.WriteLine(ReferenceEquals(s1, s3)); // false

但「動態」的定義並不簡單。對比 code06 與 code10,僅 string s1 = GetStr(); 位置不同,結果卻大相徑庭——位置差異導致觸發駐留機制的條件不同,這正是透過實例反向驗證的最佳體現。

後續探討方向

作為字串駐留機制探討的第一篇,我們從問題出發引出定義與概念。未來篇章將說明:

  • CLR 載入過程
  • intern pool 建立時機與方式
  • 駐留機制簡述
  • 方法呼叫過程
  • IsInterned 與 Intern 方法介紹
  • string intern 的失效與弊端

並力圖解釋開篇 8 個示例的結果,對可能情況進行對比推敲。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved