String.Trim()方法到底為我們做了什么,僅僅是去除字符串兩端的空格嗎?
一直以為Trim()方法就是把字符串兩端的空格字符給刪去,其實我錯了,而且錯的比較離譜。
首先我直接反編譯String類,找到Trim()方法:
1 public string Trim() 2 { 3 return this.TrimHelper(WhitespaceChars, 2); 4 }
TrimHelper方法有兩個參數,第一個參數名WhitespaceChars,首字母盡然是大寫的,肯定有文章,真不出我所料:
1 internal static readonly char[] WhitespaceChars;
這里只是定義它,沒有賦值,而且是靜態的,我們看看構造函數去,果然找到:
1 static String() 2 { Empty = " "; WhitespaceChars = new char[] { '/t', '/n', '/v', '/f', '/r', ' ', '/x0085', '/x00a0', '?', ' ', ' ', ' ', ' ', '?', '?', '?', '?', '?', ' ', '?', '?', '/u2028', '/u2029', ' ', '?' }; }
繼續我們的探索,直接反編譯TrimHelper,哇,也許這個才是我想要的,私有的TrimHelper方法:
1 private string TrimHelper(char[] trimChars, int trimType) 2 { 3 int num = this.Length - 1; 4 int startIndex = 0; 5 if (trimType != 1) 6 { 7 startIndex = 0; 8 while (startIndex < this.Length) 9 { 10 int index = 0; 11 char ch = this[startIndex]; 12 index = 0; 13 while (index < trimChars.Length) 14 { 15 if (trimChars[index] == ch) 16 { 17 break; 18 } 19 index++; 20 } 21 if (index == trimChars.Length) 22 { 23 break; 24 } 25 startIndex++; 26 } 27 } 28 if (trimType != 0) 29 { 30 num = this.Length - 1; 31 while (num >= startIndex) 32 { 33 int num4 = 0; 34 char ch2 = this[num]; 35 num4 = 0; 36 while (num4 < trimChars.Length) 37 { 38 if (trimChars[num4] == ch2) 39 { 40 break; 41 } 42 num4++; 43 } 44 if (num4 == trimChars.Length) 45 { 46 break; 47 } 48 num--; 49 } 50 } 51 int length = (num - startIndex) + 1; 52 if (length == this.Length) 53 { 54 return this; 55 } 56 if (length == 0) 57 { 58 return Empty; 59 } 60 return this.InternalSubString(startIndex, length, false); 61 }
經過分析和運行,基本上知道了這個方法是干什么的了。
TrimHelper方法有兩個參數:
第一個參數trimChars,是要從字符串兩端刪除掉的字符的數組;
第二個參數trimType,是標識Trim的類型。就目前發現,trimType的取值有3個。當傳入0時,去除字符串頭部的空白字符,傳入1時去除字符串尾部的空白字符,傳入其他數值(比如2) 去除字符串兩端的空白字符。
最后再看看真正執行字符串截取的方法:
1 private unsafe string InternalSubString(int startIndex, int length, bool fAlwaysCopy) 2 { 3 if (((startIndex == 0) && (length == this.Length)) && !fAlwaysCopy) 4 { 5 return this; 6 } 7 string str = FastAllocateString(length); 8 fixed (char* chRef = &str.m_firstChar) 9 { 10 fixed (char* chRef2 = &this.m_firstChar) 11 { 12 wstrcpy(chRef, chRef2 + startIndex, length); 13 } 14 } 15 return str; 16 }
原來也用指針的?第一次看到,效率應該比較高吧。
最后總結一下:
String.Trim()方法會去除字符串兩端,不僅僅是空格字符,它總共能去除25種字符:
('/t', '/n', '/v', '/f', '/r', ' ', '/x0085', '/x00a0', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '?', '/u2028', '/u2029', ' ', '?')
如果你想保留其中的一個或多個(例如/t制表符,/n換行符,/r回車符等),請慎用Trim方法。
請注意,Trim刪除的過程為從外到內,直到碰到一個非空白的字符為止,所以不管前后有多少個連續的空白字符都會被刪除掉。
最后附上兩個相關的方法(也是String類直接提供的),分別去除字符串頭部空白字符的TrimStart方法和去除字符串尾部空白字符的 TrimEnd方法:
TrimStart和TrimEnd方法
如果想去除字符串兩端其他任意字符,可以考慮Trim他的重載兄弟:String.Trim(Char[]),傳入你想要去除的哪些字符的數組。
源碼奉上:
1 public string Trim(params char[] trimChars) 2 { 3 if ((trimChars == null) || (trimChars.Length == 0)) 4 { 5 trimChars = WhitespaceChars; 6 } 7 return this.TrimHelper(trimChars, 2); 8 }
空格 != 空白字符,刪除空格請使用: Trim(‘ ‘);