String - 興趣解讀

来源:http://www.cnblogs.com/shouce/archive/2016/01/13/5126142.html
-Advertisement-
Play Games

作者:SmlAnt出處:http://www.cnblogs.com/smlAnt一、概述String是我們平常用得最多的基元類型之一,雖然我們經常使用而且感到非常熟悉;但很多朋友只知道一個字元串的定義、使用或知道如何使用StringBuilder來達到高效構建字元串,但是有多少朋友有興趣去瞭解背後...


作者:SmlAnt

出處:http://www.cnblogs.com/smlAnt

一、概述

String是我們平常用得最多的基元類型之一,雖然我們經常使用而且感到非常熟悉;但很多朋友只知道一個字元串的定義、使用或知道如何使用StringBuilder來達到高效構建字元串,但是有多少朋友有興趣去瞭解背後的一些“不為我們知道的秘密”?

二、為什麼把String加入到基元類型中

在以前的面向過程語言中,並沒有String這個類型,定義一個字元串的方式則採用一個Char[],雖然提供了對字元串的操作、比較等函數,但是還是不夠方便也不太符合面向對象做法,所以在面向對象語言中,string也加入了基元類型的隊列中;

三、String核心特征immutable(不可變)

代表一個不可變的順序字元集,也就是說一經創建,字元串編不能以任何方式進行修改;具有以下3個優點:

1.     允許在一個字元串上執行各種操作,而不實際地更改字元串;

2.     在操作或訪問一個字元串的時候不會發生線程同步的問題;

3.     基於性能的考慮,String類型與CLR緊密集成,CLR知道String類型中定義的欄位如何佈局,而且CLR會直接訪問,所以開發的時只好將String定義為密封類(Sealed);

四、被重寫的兩個方法GetHashCode與Equals

1.     GetHashCode方法進行了重寫,目的是為了滿足兩個字元串的判斷;

2.     Equals方法進行重寫,其中Equals方法最終還是調用了GetHashCode方法來進行判斷;

五、“==”、Equals、Compare,字元串判斷到底用哪個好點?

1.     String對“==”操作符進行重載,內部實現進行了空值判斷後,再調用Equals進行判斷(所以採用"=="操作符,不會拋出空指針異常)

2.     String的Equals方法,因為調用Equals方法的時候,直接通過返回HashCode進行比較,效率最高,有可能對象為空,有可能會拋空指針異常,所以用的時候需要留意;

3.     String的Compare方法:該方法是一個靜態方法,內部實現是首先判斷字元串的長度是否相等,如果長度不相等,直接返回結果,如果長度相等,則會採用逐個字元進行判斷,如果方法中的CultureInfo不為空,則判斷的過程中會逐個字元進行展開(這裡涉及到語言的問題,如果採用德語會把"β"展開為"ss",所以”strasse”跟”staβe”的判斷結果是相同的); 

註:如果一般情況下,建議採用Equals進行判斷,效率最高,但如果無法確保方法Equals的調用者是否不為null,建議還是採用==或者 "XXXX".Equals(obj),如果需要用到多語言(國際化)判斷的時候,可以考慮用Compare;

六、拘留池(Interning)

字元串操作(比如Compare)的做法是很多程式常見的操作,這樣的操作可能造成記憶體中複製同一個字元串的多個實例(演算法內部操作導致),為了達到節省記憶體的效果,CLR採用了一種叫“字元串留用的技術”(String Interning),開闢了一塊名為“拘留池”的空間專門用於存放字元串,而拘留池在程式初始化的時候,會把元數據預設載入到“拘留池”中,而且不會受到垃圾回收器的影響,只有在程式被關閉的時候才會釋放“拘留池”中的資源;

七、存儲方式,大致分為以下3種:

1.     以常量的方式來定義很保存字元串,比如:var value = "abc";

2.     以對象的方式來保存到堆中:比如 var value = new string('a');

3.     以對象的方式構造然後存放到拘留池(其實常量的方式定義後,預設也會把字元串加入到駐留池中); 

可以參考以下代碼和記憶體分配圖進行理解:

複製代碼     //驗證字元串常量預設載入到元數據,預設會把元數據中的字元串載入到拘留池
var data = "abc";       //此聲明方式,會把該變數定義為字元串常量,然後存入元數據中
    var a = "a";            //同上
    var b = "b";            //同上
    var c = "c";            //同上
    var ab = a + b;         //根據線程棧上的a、b地址獲取到堆上的a、b實例,然後把兩個實例的結果進行運算後產生一個新對象,最後新對象地址賦給ab變數
    var abc = a + b + c;    //同上
    var abResult = string.IsInterned(ab);        //返回結果為null,也就是說沒有把字元串"ab"存入拘留池中;
    var abcResult = string.IsInterned(abc);     //返回結果為"abc",也就是說已經把字元串(這裡是常量)"abc"存放到拘留池中;
    var empty = string.Empty;        //初始化的時候,從String類型對象中獲取靜態屬性Empty的數據;
    var strEmpty = "";               //產生一個值為空的String對象; 複製代碼

    var a1 = "abc";
    var a2 = string.IsInterned(a1);
    var result = object.ReferenceEquals(a1, a2);    

            

     註:預設是不從拘留池中載入,而是直接採用ldstr的特殊指令獲得字元串”abc”,但可以確認的是”元數據”跟“拘留池”中的字元串是用個對象; 

八、案例分析

複製代碼   1. 以下代碼的HashCode是否相同,它們是否是同個對象;

      var A = "ab" + "c";
      var B = "abc";
 
  2. 以下代碼的HashCode是否相同,他們是否是同個對象:  
      var A = Console.ReadLine();   //輸入"abc"
      var B = Console.ReadLine();   //輸入"abc"
 
  3. 以下代碼的HashCode是否相同,他們是否是同個對象:
      var A = Console.ReadLine(); //輸入"abc"
      var B = Console.ReadLine(); //輸入"abc"
      var A = string.Intern(B);

複製代碼

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • MongoDB提供的C#開發介面,先從下載開始,然後是插入、查詢、更新。先要開啟MongoDB服務。下載http://github.com/mongodb/mongo-csharp-driver/downloads.每個版本會有兩個驅動模式,一個是.msi,一個是.zip。VS:2013,Mongo...
  • 首先奉獻caching的開源地址[微軟源碼]1.工程架構為了提高程式效率,我們經常將一些不頻繁修改,但是使用了還很大的數據進行緩存。尤其是互聯網產品,緩存可以說是提升效率優化第一利器。微軟為我們實現了倆種緩存方式:記憶體緩存、分散式緩存。個人理解如果緩存在前端電腦記憶體的緩存叫做記憶體緩存,如果緩存在其它...
  • 1、許可權問題解決辦法:更改網站許可權,添加“IIS_IUsers”和“Users”兩個用戶的完全許可權2、framework版本問題更改應用程式池 版本4.0,管道經典3、“無法啟動應用程式池”錯誤打開服務,啟動Windows Process Activation Service服務4、“無法啟動網站”...
  • 有combox控制項,命名為cbxPutStatus,在程式中為其手工定義數據源,並綁定 private void POrderSplitFrm_Load(object sender, EventArgs e) { //綁定定單狀態 this.cbxPutStatus.DataSource = Dat...
  • powershell對txt文件的伺服器進行ping操作,txt文件有幾百台伺服器要進行Ping操作。每行一個#//*************************************************************#//編輯人:#//編輯單位:#//編輯作用:ping#//編...
  • 本節講Asp.net 5的緩衝。解決方案可以通過網址:https://github.com/aspnet/Caching下載也是Asp.net 5開源代碼介紹的第6部分,前5部分鏈接如下: 1. DependencyInjection(依賴註入)項目代碼分析 2. Configuration 新.....
  • 數據結構,無外乎三:1. 一對一,線性表,數組是也;2. 一對多,樹,菜單是也;3. 多對多,圖,網路是也。涉及到樹,有一個平衡的問題,左旋轉,右旋轉,轉得人暈暈乎乎。好在陳廣的《數據結構C#描述》講解非常詳盡,值得一讀。對照該書的例子,採用反編譯的手段,寫了個小程式,主要的目的是為了學習方便,也便...
  • C#中的yield可以應用在一個可迭代的方法中,我們必須真正理解此關鍵詞,才能將它正確的應用到實際生產中。為了說明yield會出現讓我們迷惑的結果,下麵先定義一個MyObject類:1 class MyObject2 {3 public int Value{get;...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...