亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

c#基礎系列之System.String的深入理解

2019-10-29 19:59:14
字體:
來源:轉載
供稿:網友

前言

幾乎任何一個項目都離不開對字符串的處理,在C和C++編程中,許多程序的漏洞都是由于字符串緩沖區溢出造成的。為了避免在C#中出現類似的問題,同時也為了使用更方便,C#中專門設置了兩個字符串處理類:String類和StringBuilder類。

本文主要給大家介紹了關于c#基礎系列之string的相關內容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧

基本概念

string(嚴格來說應該是System.String) 類型是我們日常coding中用的最多的類型之一。那什么是String呢?^ ~ ^

String是一個不可變的連續16位的Unicode代碼值的集合,它直接派生自System.Object類型。

與之對應的還有一個不常用的安全字符串類型System.Security.SecureString,它會在非托管的內存上分配,以便避開GC的黑手。主要用于安全性特高的場景。[具體可查看msdn這里不展開討論了。=>msdn查看詳情

特性

  • 由于String類型直接派生于Object,所以它是引用類型,那就意味著String對象的實例總是存在于堆上。
  • String具有不變性,也就是說一旦初始化,它的值將永遠不變。
  • String類型是封閉的,換言之,你的任何類型不能繼承String。
  • 定義字符串實例的關鍵字string只是System.String 類型的一個映射。

c#,System.String

注意事項

  • 關于字符串中的回車符和換行符一般大家喜歡直接硬編碼‘/r/n',但是不建議這么做,一旦程序遷移到其他平臺,將出現錯誤。相反,推薦使用System.Environment類的NewLine屬性來生成回車符和換行符,可以跨平臺使用的。
  • 常量字符串的拼接和非常量字符串在CLR中行為是不一樣的。具體請查看性能部分。
  • 字符串之前加@符號會改變編譯器的行為,如果加了@符號,編譯器會把String中的轉義字符視為正常字符來顯示。也就是我定義的什么內容就是什么內容,主要在使用文件路徑或者目錄字符串中使用。以下兩個String內容的輸出將完全一致。
  static void Main(string[] args)   {    string a = "c://temp//1";    string b = @"c:/temp/1";    Console.WriteLine(a);    Console.WriteLine(b);    Console.Read();      } 

性能

  • c#的編譯器直接支持String類型,并將定義的常量字符串在編譯期直接存放到模塊的元數據中。然后會在運行時直接加載。這也說明String類型的常量在運行時是有特殊待遇的。
  • 由于字符串的不變性,也就意味著多個線程同時操作該字符串不會有任何線程安全的問題。這在某些共享配置的設計中很有用。
  • 如果程序經常會對比重復度比較高的字符串,這會造成性能上的影響,因為對比字符串是要經過幾個步驟的。為此CLR引入了一個字符串重用的技術,學名叫做‘字符串留用'。原理就是:CLR會在初始化的時候創建一個內部的哈希表,key是字符串,value就是留用字符串在托管堆上的引用。
    String類型提供了兩個靜態方法來操作這個哈希表:

String.Intern

String.IsInterned

具體請查看msdn(https://msdn.microsoft.com/zh-cn/library/system.string.isinterned(v=vs.110).aspx)

但是c#編譯器默認是不開啟字符串留用功能的,因為如果程序大量把字符串留用,應用程序總體性能可能會變得更慢。(微軟也是挺糾結的,程序員TMD的更糾結)

如果我們的程序中有很多個一模一樣值的常量字符串, c#的編譯器會在編譯期間把這些字符串合并為一個并寫入模塊的元數據中,然后修改所有引用該字符串的代碼。這也是一種字符串重用技術,學名‘字符串池'。這意味著什么呢?這意味著所有值相同的常量字符串其實引用的是同一個內存地址的實例,在相同值非常多的情況下能顯著提高性能和節省大量內存。

string s1 = "hello 大菜";string s2 = "hello 大菜";unsafe{ fixed (char* p = s1) {  Console.WriteLine("字符串地址= 0x{0:x}", (int)p); } fixed (char* p = s2) {  Console.WriteLine("字符串地址= 0x{0:x}", (int)p); }} 

輸出結果:

字符串地址= 0x80002d84
字符串地址= 0x80002d84

可見實例的值只分配了一次,但是有一點需要說明,字符串僅用于編譯期能確定值的字符串,也就是常量字符串。如果我的程序修改為:

args = new string[] { "dfasfdsa"};string s1 = "hello 大菜"+ args[0];string s2 = "hello 大菜"+args[0];unsafe{ fixed (char* p = s1) {  Console.WriteLine("字符串地址= 0x{0:x}", (int)p); } fixed (char* p = s2) {  Console.WriteLine("字符串地址= 0x{0:x}", (int)p); }}

運行結果:

字符串地址= 0x2e3c
字符串地址= 0x2e7c

平時coding避免不了字符串的連接,如果一個頻繁拼接字符串的場景下使用‘+',對程序整體性能和GC影響還是挺大的,為此c#推出了 StringBuilder類型來優化字符串的拼接。相對于String類型的不變性來說,StringBuilder更像是可變的字符串類型。它的底層數據結構是一個Char的數組。另外還有容量(默認為16),最大容量(默認為int.MaxValue)等屬性。StringBuilder的優勢在于字符總數未超過‘容量'的時候,底層數組不會重新分配,這和String每次都重新分配形成最大的對比。如果字符總數超過‘容量',StringBuilder會自動倍增容量屬性,用一個新的數組來容納原來的值,原來數組將會被GC回收??梢娙绻鸖tringBuilder頻繁的動態擴容也會損害性能,但是影響可能會比String小的多。 合理的設置StringBuilder初始容量對程序有很大幫助。測試如下:

int count = 100000;Stopwatch sw = new Stopwatch();sw.Start();string s = "";for (int i = 0; i < count; i++) {  s += i.ToString(); }sw.Stop();Console.WriteLine(sw.ElapsedMilliseconds);

運行結果:

14221

查看GC的情況

c#,System.String

Gc執行的是如此頻繁。 性能是可想而知的。接著看一下StringBuilder

int count = 100000;Stopwatch sw = new Stopwatch();sw.Start();   StringBuilder sb = new StringBuilder();//聽說程序員都這樣命名StringBuilderfor (int i = 0; i < count; i++) { sb.Append(i.ToString());}sw.Stop();Console.WriteLine(sw.ElapsedMilliseconds);

運行結果:

12

GC情況:

c#,System.String

幾乎沒有GC(可能還未達到觸發GC的臨界點),如果我合理初始化了StringBuilder 容量,生產環境中結果差距將會更大。 呵呵 ^ ~ ^

其他

關于字符串留用和字符串池

一個程序集加載的時候,CLR默認會留用該程序集元數據中描述的所有文本常量字符串。由于可能會出現額外的哈希表查找造成的性能下降的現象,所以現在可以禁用這個特性了。

coding中我們平常比較兩個字符串是否相等,那這個過程是怎么樣的呢?

  • 首先判斷字符的數量是否相等。
  • CLR逐個對比字符最終確定是否相等。

這個場景是適合字符串留用的。因為不再需要經過以上的兩個步驟,直接哈希表拿到value就可以對比確定了。

關于字符串拼接性能

基于以上所有知識,那是不是StringBuilder拼接字符串性能永遠都高于符號‘+'呢?答案是否定的。

 static void Main(string[] args)  {   int count = 10000000;   Stopwatch sw = new Stopwatch();   sw.Start();      string str1 = "str1", str2 = "str2", str3 = "str3";   for (int i = 0; i < count; i++)   {    string s = str1 + str2 + str3;   }   sw.Stop();   Console.WriteLine($@"+用時: {sw.ElapsedMilliseconds}" );   sw.Reset();   sw.Start();   for (int i = 0; i < count; i++)   {    StringBuilder sb = new StringBuilder();//聽說程序員都這樣命名StringBuilder    sb.Append(str1).Append(str2).Append(str3);   }   sw.Stop();   Console.WriteLine($@"StringBuilder.Append 用時: {sw.ElapsedMilliseconds}");   Console.Read();  }

運行結果:

+用時: 553
StringBuilder.Append 用時: 975

符號‘+'最終會調用String.Concat方法,當同時連接幾個字符串時,并不是每連接一個都分配一次內存,而是把幾個字符都作為 String.Concat方法的參數,只分配一次內存。所以在拼接的字符串個數比較少的場景下,String.Concat 性能是略高于StringBuilder.Append。string.Format 方法最終調用的是StringBuilder,這里不做展開討論了,請自行參考其他文檔。

所以萬事都不是絕對的!!每個事物都有適合自己的場景,我們都需要自己去探索。(程序員太累了)

以上都是非生產環境測試結果,如果錯誤,請及時指正

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到c#教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人免费视频xnxx.com| 久久精品国产久精国产一老狼| 成人在线视频网站| 91色琪琪电影亚洲精品久久| 亚洲欧美日韩一区二区在线| 狠狠操狠狠色综合网| 国产suv精品一区二区| 中文字幕在线日韩| 国产精品久久久久久久久男| 岛国av一区二区| 国产成人精品久久二区二区91| 91av视频在线| 最近中文字幕mv在线一区二区三区四区| 国产综合久久久久| 日韩天堂在线视频| 久久久噜噜噜久噜久久| 亚洲精品在线91| 欧美日韩在线影院| 国产一区二区三区久久精品| 91国产视频在线| 综合136福利视频在线| 国产精品69精品一区二区三区| 九九热在线精品视频| 米奇精品一区二区三区在线观看| 国产精品美女久久久久av超清| 在线观看精品国产视频| 热99精品里视频精品| 成人妇女淫片aaaa视频| 日本精品va在线观看| 欧美老女人www| 国产精品福利在线观看| 国产精品人成电影| 欧美日韩国产一区中文午夜| 欧美激情视频在线| 国产91精品久久久久久| 成人久久一区二区三区| 日韩欧美在线视频免费观看| 91精品国产自产在线老师啪| 成人免费激情视频| 九九精品视频在线观看| 久久久av网站| 成人精品视频99在线观看免费| 日韩精品在线观| 亚洲一区二区少妇| 欧美中文字幕在线| 日日噜噜噜夜夜爽亚洲精品| 日韩成人av网| 久久久久久国产精品三级玉女聊斋| 久久伊人精品天天| 高清欧美性猛交| 欧美极品xxxx| 中国china体内裑精亚洲片| 亚洲老板91色精品久久| 欧美极品在线播放| 日韩av在线网址| 久久的精品视频| 成人免费xxxxx在线观看| 欧美日韩美女在线| 欧美丝袜一区二区三区| 亚洲图片欧洲图片av| 中文字幕日韩在线播放| 亚洲精品欧美一区二区三区| 7m第一福利500精品视频| 亚洲国产免费av| 日韩69视频在线观看| 国产精品色午夜在线观看| 日韩欧美亚洲国产一区| 亚洲电影av在线| 国产成人av在线| 国产精品久久久久久久久久| 在线观看视频亚洲| 色综合视频一区中文字幕| 在线播放日韩精品| 怡红院精品视频| 国产福利视频一区二区| 亚洲精品资源美女情侣酒店| 国产精品久久久久久中文字| 国产精品av免费在线观看| 欧美乱大交xxxxx| 亚洲免费电影一区| 在线看欧美日韩| 久久久天堂国产精品女人| 亚洲黄色在线观看| 亚洲一区二区福利| 亚洲图中文字幕| 国产欧美一区二区三区在线| 国产精品一区专区欧美日韩| 国产成人久久久精品一区| 日韩免费av一区二区| 日韩欧中文字幕| 国产精品视频自在线| 色诱女教师一区二区三区| 日韩免费av一区二区| 亚洲a中文字幕| 日韩免费av在线| 国产精品免费久久久| 亚洲国产精品久久久久秋霞蜜臀| 国外成人性视频| 亚洲在线免费观看| 欧美极品少妇与黑人| 92版电视剧仙鹤神针在线观看| 欧美日韩一区二区三区| 亚洲午夜性刺激影院| 国产精品久久精品| 精品色蜜蜜精品视频在线观看| 国产成人精品综合久久久| 欧美性高潮床叫视频| 国产精品久久久久久久av电影| 亚洲视频电影图片偷拍一区| 97碰碰碰免费色视频| 日韩精品在线观看网站| 中文字幕日本欧美| 日韩激情av在线免费观看| 7m第一福利500精品视频| 色偷偷噜噜噜亚洲男人| 亚洲人成在线观| 不卡在线观看电视剧完整版| 91在线高清视频| 亚洲人成网站999久久久综合| www.色综合| 久久久国产在线视频| 98精品国产自产在线观看| 国产精品美女久久久久av超清| 久久综合免费视频影院| 26uuu久久噜噜噜噜| 亚洲自拍偷拍视频| 夜夜躁日日躁狠狠久久88av| 欧美日韩精品在线观看| 日本中文字幕久久看| 欧美性高潮在线| 国产女精品视频网站免费| 91嫩草在线视频| 国产女人精品视频| 在线观看免费高清视频97| 国产精品色婷婷视频| 亚洲第一男人天堂| 在线观看国产精品日韩av| 欧美另类69精品久久久久9999| 少妇高潮久久久久久潘金莲| 日韩精品在线免费播放| 亚洲欧美日韩直播| 亚州av一区二区| 亚洲国产另类 国产精品国产免费| 91夜夜揉人人捏人人添红杏| 日本亚洲欧美三级| 国产日韩在线看片| 欧美日韩国产麻豆| 日韩在线精品一区| 国产亚洲精品久久久久久777| 日韩欧美亚洲范冰冰与中字| 国产精品自产拍在线观看中文| 亚洲欧洲在线免费| 欧美成人网在线| 国产亚洲日本欧美韩国| 亚洲欧美激情一区| 丰满岳妇乱一区二区三区| 久久精品电影网| 日韩经典中文字幕在线观看| 久久精品电影网站| 欧美日韩激情视频8区| 97精品久久久中文字幕免费| 亚洲最大av网站| 亚洲精品成a人在线观看| 欧美亚洲另类制服自拍|