《CLR Via C# 第3版》笔记之(十六) - 字符串

.Net中的字符串是被谈论最多的话题,这里也进行一些总结,供以后参考。

主要内容:

  • 字符串的不可变性和字符串留用
  • 语言文化
  • 格式化器 

1. 字符串的不可变性和字符串留用

字符串(string)在.Net中是一个特殊的类。

.Net中的字符串是不可变的(immutable)。也就是说,字符串已经创建就不能更改,变长,变短,修改字符都不行。

对字符串进行的任何操作都不能改变原字符串,只会生成新的字符串。

由于String是不可变的,我们在使用大量的字符串拼接的时候不宜使用 【+】运算符,比如

1
"A"  + "B"  + "C"

而是可以使用StringBuilder这个类,

1
2
3
4
StringBuilder sb = new  StringBuilder();
sb.Append( "A" );
sb.Append( "B" );
sb.Append( "C" );

这样可以避免在内存中不断生成新的string对象。

StringBuilder的工作原理大致是这样的:

内部维护一个字符数组,并且有一个初始容量。

新的字符串都加入到这个数组中。

当加入的字符超过容量时,就重新new一个更大的数组,并将原先的数组内容拷入新数组中。

将原有的数组进行垃圾回收,新的字符串加入到使用新的字符数组中。

StringBuilder的ToString方法见字符数组转换为一个String输出。

 

为了提高字符串的性能,.Net中对已有的字符串进行了留用,使得再次使用相同的字符串时不用重新申请内存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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. 语言文化

字符串的语言文化在使用中很少涉及,但是如果不注意的话,可能会遇到意料之外的错误。

如以下中文和日语的比较,用不同的语言文化,比较结果就不同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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,则直接输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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
}
标签:  CLR via C#笔记


本文转自wang_yb博客园博客,原文链接:http://www.cnblogs.com/wang_yb/archive/2011/10/21/2220495.html,如需转载请自行联系原作者

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值