《CLR Via C# 第3版》筆記之(十六) - 字符串
.Net中的字符串是被談論最多的話題,這里也進行一些總結,供以后參考。
主要內容:
- 字符串的不可變性和字符串留用
- 語言文化
- 格式化器
1. 字符串的不可變性和字符串留用
字符串(string)在.Net中是一個特殊的類。
.Net中的字符串是不可變的(immutable)。也就是說,字符串已經創建就不能更改,變長,變短,修改字符都不行。
對字符串進行的任何操作都不能改變原字符串,只會生成新的字符串。
由于String是不可變的,我們在使用大量的字符串拼接的時候不宜使用 【+】運算符,比如
"A" + "B" + "C"
而是可以使用StringBuilder這個類,
StringBuilder sb = new StringBuilder();
sb.Append("A");
sb.Append("B");
sb.Append("C");
這樣可以避免在內存中不斷生成新的string對象。
StringBuilder的工作原理大致是這樣的:
內部維護一個字符數組,并且有一個初始容量。
新的字符串都加入到這個數組中。
當加入的字符超過容量時,就重新new一個更大的數組,并將原先的數組內容拷入新數組中。
將原有的數組進行垃圾回收,新的字符串加入到使用新的字符數組中。
StringBuilder的ToString方法見字符數組轉換為一個String輸出。
為了提高字符串的性能,.Net中對已有的字符串進行了留用,使得再次使用相同的字符串時不用重新申請內存。
using System;
public class CLRviaCSharp_16
{
static void Main(string[] args)
{
string s1 = "Hello";
string s2 = "Hello";
// 應該為 False
Console.WriteLine(object.ReferenceEquals(s1, s2));
s1 = String.Intern("Hello");
s2 = String.Intern("Hello");
// 顯示 True
Console.WriteLine(object.ReferenceEquals(s1, s2));
Console.ReadKey(true);
}
}
第一次的執行結果應該為False,但是CLR在編譯時默認進行了留用,所以2次結果都是True
我們如果要使用字符串留用的話,一定要明確使用String.Intern,否則CLR版本變更后有可能不默認進行字符串留用。
那樣,運行結果就變了。
2. 語言文化
字符串的語言文化在使用中很少涉及,但是如果不注意的話,可能會遇到意料之外的錯誤。
如以下中文和日語的比較,用不同的語言文化,比較結果就不同。
using System;
using System.Globalization;
public class CLRviaCSharp_16
{
static void Main(string[] args)
{
string s1 = "中文";
string s2 = "日本語";
CompareInfo compareInfo = CompareInfo.GetCompareInfo("ja-JP");
Console.WriteLine(compareInfo.Compare(s1, s2));
compareInfo = CompareInfo.GetCompareInfo("zh-CN");
Console.WriteLine(compareInfo.Compare(s1, s2));
Console.ReadKey(true);
}
}
在不同語言之間進行字符串比較需要注意語言文化對結果的影響。
3. 格式化器
通過格式化器,可以將字符串按照一定的格式輸出,在打印或者log輸出上會很有用。
實現自定義的格式化器需要繼承IFormatProvider, ICustomFormatter兩個接口。
下面通過例子演示如何通過定制格式化器來調整打印輸出的。
例子很簡單,依次輸出字符串,
如果字符串長度大于4,則截斷尾部,只輸出4個字符。
如果字符串長度小于4,則在尾部補充【*】,使長度達到4。
如果字符串長度等于4,則直接輸出。
using System;
public class CLRviaCSharp_16
{
static void Main(string[] args)
{
string[] strs = new string[] { "sadfasdf", "dgdgfdsds", "ggh", "w", "abcd" };
foreach (var str in strs)
{
Console.WriteLine(string.Format(new FormatPrint(), "{0}", str));
}
Console.ReadKey(true);
}
}
internal class FormatPrint : IFormatProvider, ICustomFormatter
{
#region IFormatProvider Members
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
else
return null;
}
#endregion
#region ICustomFormatter Members
public string Format(string format, object arg, IFormatProvider formatProvider)
{
string s;
IFormattable formattable = arg as IFormattable;
if (formattable == null)
s = arg.ToString();
else
s = formattable.ToString(format, formatProvider);
// 開始處理長度
if (s.Length > 4)
return s.Substring(0, 4);
else if (s.Length == 4)
return s;
for (int i = s.Length; i < 4; i++)
s += "*";
return s;
}
#endregion
}

浙公網安備 33010602011771號