国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

String-興趣解讀

2019-11-14 13:33:31
字體:
來源:轉載
供稿:網友

作者:SmlAnt

出處:http://www.survivalescaperooms.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);

復制代碼

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 平湖市| 华坪县| 兴海县| 旌德县| 大庆市| 白城市| 海原县| 苍南县| 普安县| 延长县| 华池县| 金堂县| 闻喜县| 葵青区| 彭州市| 大港区| 孟州市| 鹿泉市| 封开县| 宜兰县| 客服| 雷波县| 德庆县| 常德市| 平利县| 平定县| 沧州市| 锦屏县| 古蔺县| 平昌县| 五指山市| 昌江| 化州市| 江源县| 岳阳市| 通海县| 阿鲁科尔沁旗| 沙湾县| 视频| 深泽县| 仁寿县|