100165354.htm
来自「C#高级编程(第三版),顶死你们。。 。up」· HTM 代码 · 共 213 行 · 第 1/3 页
HTM
213 行
<p class="a1" style="FTEL: 21.45pt"><span style="FONT-FAMILY: 楷体_GB2312">为了简单起见,这段代码没有把</span><span lang="EN-US">Z</span><span style="FONT-FAMILY: 楷体_GB2312">换成</span><span lang="EN-US">A</span><span style="FONT-FAMILY: 楷体_GB2312">,或把</span><span lang="EN-US">z</span><span style="FONT-FAMILY: 楷体_GB2312">换成</span><span lang="EN-US">a</span><span style="FONT-FAMILY: 楷体_GB2312">。这些字符分别编码为</span><span lang="EN-US">[</span><span style="FONT-FAMILY: 楷体_GB2312">和</span><span lang="EN-US">{</span><span style="FONT-FAMILY: 楷体_GB2312">。</span></p>
<p class="MsoNormal"><span lang="EN-US">Replace()</span><span style="FONT-FAMILY: 宋体">以一种智能化的方式工作,在某种程度上,它并没有实际创建一个新字符串,除非要对旧字符串进行某些改变。原来的字符串包含</span><span lang="EN-US">23</span><span style="FONT-FAMILY: 宋体">个不同的小写字母,和</span><span lang="EN-US">3</span><span style="FONT-FAMILY: 宋体">个不同的大写字母。所以</span><span lang="EN-US">Replace()</span><span style="FONT-FAMILY: 宋体">就分配一个新字符串,共</span><span lang="EN-US">26</span><span style="FONT-FAMILY: 宋体">次,每个新字符串都包含</span><span lang="EN-US">103</span><span style="FONT-FAMILY: 宋体">个字符。因此加密过程需要在堆上有一个能存储总共</span><span lang="EN-US">2678</span><span style="FONT-FAMILY: 宋体">个字符的字符串对象,最终将等待被垃圾收集!显然,如果使用字符串进行文字处理,应用程序就会有严重的性能问题。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">为了解决这个问题,</span><span lang="EN-US">Microsoft</span><span style="FONT-FAMILY: 宋体">提供了</span><span lang="EN-US">System.Text.StringBuilder</span><span style="FONT-FAMILY: 宋体">类。</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">不像</span><span lang="EN-US">String</span><span style="FONT-FAMILY: 宋体">功能那么强大,后者已有那么多所支持的方法。在</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">上可以进行的处理仅限于替换和添加或删除字符串中的文本。但是,它的工作方式非常高效。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">在构造一个字符串时,要给它分配足够的内存来保存字符串,但</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">通常分配的内存会比需要的更多。可以选择显式指定要分配多少内存,但如果没有显式指定,存储单元量在默认情况下就根据</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">初始化时的字符串长度来确定。它有两个主要的属性:</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; FTEL: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span lang="EN-US">Length</span><span style="FONT-FAMILY: 宋体">指定字符串的实际长度;</span></p>
<p class="1" style="MARGIN-LEFT: 37.55pt; FTEL: -16.1pt"><span lang="EN-US">●<span style="FONT: 7pt 'Times New Roman'"> </span></span><span lang="EN-US">Capacity</span><span style="FONT-FAMILY: 宋体">是字符串占据存储单元的长度。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">对字符串的修改就在赋予</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">实例的存储单元中进行,这就大大提高了添加子字符串和替换单个字符的效率。删除或插入子字符串仍然效率低下,因为这需要移动随后的字符串。只有执行扩展字符串容量的操作,才会给字符串分配需要的新内存,才可能移动整个包含的字符串。在编写本书的过程中,</span><span lang="EN-US">Microsoft</span><span style="FONT-FAMILY: 宋体">并没有说明会添加多少额外的容量,但从经验来看,</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">如果检测到容量超出,且该容量中没有显示设置新值,就会使自己的容量翻倍。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">例如,如果使用</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">对象构造最初的欢迎字符串,可以编写下面的代码:</span></p>
<p class="2" style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><a ftel="StringBuilder1"><span lang="EN-US">StringBuilder greetingBuilder =</span></a></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> new StringBuilder("Hello from all the guys at Wrox Press. ", 150);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US">greetingBuilder.Append("We do hope you enjoy this book as much as we enjoyed writing it");</span></p>
<p class="2" style="MARGIN-TOP: 0cm; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US"> </span></p>
<p class="a3" style="MARGIN-TOP: 8.15pt; FTEL: 21.45pt"><span style="FONT-FAMILY: 黑体">注意:</span></p>
<p class="a1" style="FTEL: 21.45pt"><span style="FONT-FAMILY: 楷体_GB2312">为了使用</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 楷体_GB2312">类,需要在代码中引用</span><span lang="EN-US">System.Text</span><span style="FONT-FAMILY: 楷体_GB2312">。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">在这段代码中,为</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">设置的初始容量是</span><span lang="EN-US">150</span><span style="FONT-FAMILY: 宋体">。最好把容量设置为字符串可能的最大长度,确保</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">不需要重新分配内存,因为其容量足够用了。理论上,可以设置尽可能大的数字,足够给该容量传送一个</span><span lang="EN-US">int</span><span style="FONT-FAMILY: 宋体">,但如果实际上给字符串分配</span><span lang="EN-US">20</span><span style="FONT-FAMILY: 宋体">亿个字符的空间</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">这是</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">实例允许拥有的最大理论空间</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">,系统就可能会没有足够的内存。</span></p>
<p class="MsoNormal" style="TEXT-ALIGN: left" align="left"><span style="FONT-FAMILY: 宋体">执行上面的代码,首先创建一个</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">对象,如图</span><span lang="EN-US">8-1</span><span style="FONT-FAMILY: 宋体">所示。</span></p>
<p align="center"><span lang="EN-US"><img height="71" src="08/image001.gif" width="451" alt="" /></span></p>
<p style="FTEL: 8.15pt" align="center"><span style="FONT-FAMILY: 宋体">图</span><span lang="EN-US"> 8-1</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">在调用</span><span lang="EN-US">Append()</span><span style="FONT-FAMILY: 宋体">方法时,其他文本就放在空的空间中,不需要分配更多的内存。但是,多次替换文本才能获得使用</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">所带来的性能提高。例如,如果要以前面的方式加密文本,就可以执行整个加密过程,无须分配更多的内存:</span></p>
<p class="a6" style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US">StringBuilder greetingBuilder =</span></p>
<p class="a6" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> new StringBuilder("Hello from all the guys at Wrox Press. ", 150);</span></p>
<p class="a6" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US">greetingBuilder.Append("We do hope you enjoy this book as much as we enjoyed writing it");</span></p>
<p class="a6" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> </span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US">for(int i = (int)'z'; i>=(int)'a' ; i--)</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US">{</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> char old1 = (char)i;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> char new1 = (char)(i+1);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> greetingBuilder = greetingBuilder.Replace(old1, new1);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US">}</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> </span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US">for(int i = (int)'Z'; i>=(int)'A' ; i</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -2pt">––</span><span lang="EN-US" style="LETTER-SPACING: -2pt"> </span><span lang="EN-US">)</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US">{</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> char old1 = (char)i;</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> char new1 = (char)(i+1);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US"> greetingBuilder = greetingBuilder.Replace(old1, new1);</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; FTEL: 18.45pt"><span lang="EN-US">}</span></p>
<p class="2" style="MARGIN-TOP: 0cm; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US">Console.WriteLine("Encoded:\n" + greetingBuilder.ToString());</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">这段代码使用了</span><span lang="EN-US">StringBuilder.Replace()</span><span style="FONT-FAMILY: 宋体">方法,它的功能与</span><span lang="EN-US">String.Replace()</span><span style="FONT-FAMILY: 宋体">一样,但不需要在过程中复制字符串。在上述代码中,为存储字符串而分配的总存储单元是</span><span lang="EN-US">150</span><span style="FONT-FAMILY: 宋体">个字符,用于</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">实例以及在最后一个</span><span lang="EN-US">Console.WriteLine()</span><span style="FONT-FAMILY: 宋体">语句中内部执行字符串操作期间分配的内存。</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">一般,使用</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">就可以执行字符串的任何操作,</span><span lang="EN-US">String</span><span style="FONT-FAMILY: 宋体">可以用于存储字符串或显示最终结果等。</span></p>
<h4 style="FTEL: 21.45pt"><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 黑体">成员</span></h4>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">前面介绍了</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">的一个构造函数,它的参数是一个初始字符串及该字符串的容量。还有几个其他的</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">构造函数,在这些</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">构造函数中,只能提供一个字</span><span lang="EN-US"> </span><span style="FONT-FAMILY: 宋体">符串:</span></p>
<p class="2" style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US">StringBuilder sb = new StringBuilder("Hello");</span></p>
<p class="MsoNormal" style="FTEL: 0cm"><span style="FONT-FAMILY: 宋体">或者用给定的容量创建一个空的</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">:</span></p>
<p class="2" style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US">StringBuilder sb = new StringBuilder(20);</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">除了前面介绍的</span><span lang="EN-US">Length </span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US"> Capacity</span><span style="FONT-FAMILY: 宋体">属性外,还有一个只读属性</span><span lang="EN-US">MaxCapacity</span><span style="FONT-FAMILY: 宋体">,它表示对给定的</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">实例的限制,最多可以有多少容量。在默认情况下,这由</span><span lang="EN-US">int.MaxValue</span><span style="FONT-FAMILY: 宋体">给定</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">大约</span><span lang="EN-US">20</span><span style="FONT-FAMILY: 宋体">亿,如前所述</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">,在构造</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">对象时,也可以把这个值设置为较低的值:</span></p>
<p class="2" style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US">// This will both set initial capacity to 100, but the max will be 500.</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 13pt; FTEL: 18.45pt"><span lang="EN-US">// Hence, this StringBuilder can never grow to more than 500 characters,</span></p>
<p class="2" style="MARGIN-LEFT: 21.45pt; LINE-HEIGHT: 13pt; FTEL: 18.45pt"><span lang="EN-US">// otherwise it will raise exception if you try to do that.</span></p>
<p class="2" style="MARGIN-TOP: 0cm; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US">StringBuilder sb = new StringBuilder(100, 500);</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">还可以随时显式地设置容量,但如果把这个值设置为低于字符串的当前长度,或者超出了最大容量,就会抛出一个异常:</span></p>
<p class="2" style="MARGIN-TOP: 8.15pt; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US">StringBuilder sb = new StringBuilder("Hello");</span></p>
<p class="2" style="MARGIN-TOP: 0cm; MARGIN-LEFT: 21.45pt; MARGIN-RIGHT: 0cm; FTEL: 18.45pt"><span lang="EN-US">sb.Capacity = 100;</span></p>
<p class="MsoNormal"><span style="FONT-FAMILY: 宋体">主要的</span><span lang="EN-US">StringBuilder</span><span style="FONT-FAMILY: 宋体">方法如表</span><span lang="EN-US">8-2</span><span style="FONT-FAMILY: 宋体">所示。</span><a ftel="StringBuildermethods"><span lang="EN-US"> </span></a></p>
<p class="a5" style="MARGIN-TOP: 8.15pt"><span style="FONT-FAMILY: 黑体">表</span><span lang="EN-US"> 8-2</span></p>
<div align="center">
<table class="MsoNormalTable" style="MARGIN-LEFT: 24.1pt; WIDTH: 441.1pt; BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-COLLAPSE: collapse; BORDER-BOTTOM-STYLE: none" cellspacing="0" cellpadding="0" width="588" border="1">
<tbody>
<tr>
<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 9.9pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 9.9pt; BORDER-LEFT-WIDTH: 1pt; BORDER-LEFT-COLOR: windowtext; PADDING-BOTTOM: 0cm; WIDTH: 106.3pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid" valign="top" width="142">
<p class="a2"><span style="FONT-FAMILY: 黑体">名</span><span lang="EN-US" style="FONT-FAMILY: 'Times New Roman'"> </span><span style="FONT-FAMILY: 黑体">称</span></p>
</td>
<td style="PADDING-RIGHT: 9.9pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 9.9pt; PADDING-BOTTOM: 0cm; WIDTH: 334.8pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none" valign="top" width="446">
<p class="a2"><span style="FONT-FAMILY: 黑体">作</span><span lang="EN-US" style="FONT-FAMILY: 'Times New Roman'"> </span><span style="FONT-FAMILY: 黑体">用</span></p>
</td>
</tr>
<tr>
<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 9.9pt; PADDING-LEFT: 9.9pt; PADDING-BOTTOM: 0cm; WIDTH: 106.3pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT-STYLE: none" valign="top" width="142">
<p class="a4" style="MARGIN-LEFT: 10.7pt"><span lang="EN-US">Append()</span></p>
</td>
<td style="PADDING-RIGHT: 9.9pt; PADDING-LEFT: 9.9pt; PADDING-BOTTOM: 0cm; WIDTH: 334.8pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none" valign="top" width="446">
<p class="a4" style="MARGIN-LEFT: 10.7pt"><span style="FONT-FAMILY: 宋体">给当前字符串添加一个字符串</span></p>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?