﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-Glacier Tribe</title><link>http://www.cnblogs.com/glacierh/</link><description>以技术引领生活</description><language>zh-cn</language><lastBuildDate>Fri, 19 Mar 2010 14:03:32 GMT</lastBuildDate><pubDate>Fri, 19 Mar 2010 14:03:32 GMT</pubDate><ttl>60</ttl><item><title>正则表达式参考文档</title><link>http://www.cnblogs.com/glacierh/archive/2010/01/21/1653709.html</link><dc:creator>Glacier</dc:creator><author>Glacier</author><pubDate>Thu, 21 Jan 2010 14:45:00 GMT</pubDate><guid>http://www.cnblogs.com/glacierh/archive/2010/01/21/1653709.html</guid><description><![CDATA[<p>阅读: 73 评论: 0 作者: <a href="http://www.cnblogs.com/glacierh/" target="_blank">Glacier</a> 发表于 2010-01-21 22:45 <a href="http://www.cnblogs.com/glacierh/archive/2010/01/21/1653709.html" target="_blank">原文链接</a></p><h4><a name="intro"></a><strong>引言</strong></h4>
<p>&nbsp;&nbsp;&nbsp; 正则表达式（regular expression）就是用一个&#8220;字符串&#8221;来描述一个特征，然后去验证另一个&#8220;字符串&#8221;是否符合这个特征。比如 表达式&#8220;ab+&#8221; 描述的特征是&#8220;一个 'a' 和 任意个 'b' &#8221;，那么 'ab', 'abb', 'abbbbbbbbbb' 都符合这个特征。</p>
<p>&nbsp;&nbsp;&nbsp; 正则表达式可以用来：（1）验证字符串是否符合指定特征，比如验证是否是合法的邮件地址。（2）用来查找字符串，从一个长的文本中查找符合指定特征的字符串，比查找固定字符串更加灵活方便。（3）用来替换，比普通的替换更强大。<br /><br />&nbsp;&nbsp; 正则表达式学习起来其实是很简单的，不多的几个较为抽象的概念也很容易理解。之所以很多人感觉正则表达式比较复杂，一方面是因为大多数的文档没有做到由浅入深地讲解，概念上没有注意先后顺序，给读者的理解带来困难；另一方面，各种引擎自带的文档一般都要介绍它特有的功能，然而这部分特有的功能并不是我们首先要理解的。<br /><br />&nbsp;&nbsp;&nbsp; 文章中的每一个举例，都可以点击进入到测试页面进行测试。闲话少说，开始。</p>
<hr color="#fea089" size="1" />

<h4>1. 正则表达式规则</h4>
<h5><a name="common"></a>1.1 普通字符</h5>
<p>&nbsp;&nbsp;&nbsp; 字母、数字、汉字、下划线、以及后边章节中没有特殊定义的标点符号，都是"普通字符"。表达式中的普通字符，在匹配一个字符串的时候，匹配与之相同的一个字符。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=c&amp;txt=abcde" target="_blank">举例1：表达式 "c"，在匹配字符串 "abcde" 时</a>，匹配结果是：成功；匹配到的内容是："c"；匹配到的位置是：开始于2，结束于3。（注：下标从0开始还是从1开始，因当前编程语言的不同而可能不同）<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=bcd&amp;txt=abcde" target="_blank">举例2：表达式 "bcd"，在匹配字符串 "abcde" 时</a>，匹配结果是：成功；匹配到的内容是："bcd"；匹配到的位置是：开始于1，结束于4。</p>
<hr color="#fea089" size="1" />

<h5><a name="escaped"></a>1.2 简单的转义字符</h5>
<p>&nbsp;&nbsp;&nbsp; 一些不便书写的字符，采用在前面加 "\" 的方法。这些字符其实我们都已经熟知了。</p>
<table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
<tr bgcolor="#f0f0f0">
<td width="70">
<p>表达式</p></td>
<td>
<p>可匹配</p></td></tr>
<tr>
<td>
<p>\r, \n</p></td>
<td>
<p>代表回车和换行符</p></td></tr>
<tr>
<td>
<p>\t</p></td>
<td>
<p>制表符</p></td></tr>
<tr>
<td>
<p>\\</p></td>
<td>
<p>代表 "\" 本身</p></td></tr></table>
<p>&nbsp;&nbsp;&nbsp; 还有其他一些在后边章节中有特殊用处的标点符号，在前面加 "\" 后，就代表该符号本身。比如：^, $ 都有特殊意义，如果要想匹配字符串中 "^" 和 "$" 字符，则表达式就需要写成 "\^" 和 "\$"。</p>
<table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
<tr bgcolor="#f0f0f0">
<td width="66">
<p>表达式</p></td>
<td>
<p>可匹配</p></td></tr>
<tr>
<td>
<p>\^</p></td>
<td>
<p>匹配 ^ 符号本身</p></td></tr>
<tr>
<td>
<p>\$</p></td>
<td>
<p>匹配 $ 符号本身</p></td></tr>
<tr>
<td>
<p>\.</p></td>
<td>
<p>匹配小数点（.）本身</p></td></tr></table>
<p>&nbsp;&nbsp;&nbsp; 这些转义字符的匹配方法与 "普通字符" 是类似的。也是匹配与之相同的一个字符。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=%5C$d&amp;txt=abc$de" target="_blank">举例1：表达式 "\$d"，在匹配字符串 "abc$de" 时</a>，匹配结果是：成功；匹配到的内容是："$d"；匹配到的位置是：开始于3，结束于5。</p>
<hr color="#fea089" size="1" />

<h5><a name="multi"></a>1.3 能够与 '多种字符' 匹配的表达式</h5>
<p>&nbsp;&nbsp;&nbsp; 正则表达式中的一些表示方法，可以匹配 '多种字符' 其中的任意一个字符。比如，表达式 "\d" 可以匹配任意一个数字。虽然可以匹配其中任意字符，但是只能是一个，不是多个。这就好比玩扑克牌时候，大小王可以代替任意一张牌，但是只能代替一张牌。</p>
<table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
<tr bgcolor="#f0f0f0">
<td width="66">
<p>表达式</p></td>
<td>
<p>可匹配</p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#900050">\d</font></font></span></p></td>
<td>
<p>任意一个数字，0~9 中的任意一个</p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#900050">\w</font></font></span></p></td>
<td>
<p>任意一个字母或数字或下划线，也就是 A~Z,a~z,0~9,_ 中任意一个</p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#900050">\s</font></font></span></p></td>
<td>
<p>包括空格、制表符、换页符等空白字符的其中任意一个</p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#900050">.</font></font></span></p></td>
<td>
<p>小数点可以匹配除了换行符（\n）以外的任意一个字符</p></td></tr></table>
<p>&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=%5Cd%5Cd&amp;txt=abc123" target="_blank">举例1：表达式 "<span id="pattern" name="pattern"><font color="#000000"><font color="#900050">\d</font><font color="#900050">\d</font></font></span>"，在匹配 "abc123" 时</a>，匹配的结果是：成功；匹配到的内容是："12"；匹配到的位置是：开始于3，结束于5。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=a.%5Cd&amp;txt=aaa100" target="_blank">举例2：表达式 "<span id="pattern" name="pattern"><font color="#000000">a<font color="#900050">.</font><font color="#900050">\d</font></font></span>"，在匹配 "aaa100" 时</a>，匹配的结果是：成功；匹配到的内容是："aa1"；匹配到的位置是：开始于1，结束于4。</p>
<hr color="#fea089" size="1" />

<h5><a name="custom"></a>1.4 自定义能够匹配 '多种字符' 的表达式</h5>
<p>&nbsp;&nbsp;&nbsp; 使用方括号 [ ] 包含一系列字符，能够匹配其中任意一个字符。用 [^ ] 包含一系列字符，则能够匹配其中字符之外的任意一个字符。同样的道理，虽然可以匹配其中任意一个，但是只能是一个，不是多个。</p>
<table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
<tr bgcolor="#f0f0f0">
<td width="80">
<p>表达式</p></td>
<td>
<p>可匹配</p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#900050">[ab5@]</font></font></span></p></td>
<td>
<p>匹配 "a" 或 "b" 或 "5" 或 "@"</p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#900050">[^abc]</font></font></span></p></td>
<td>
<p>匹配 "a","b","c" 之外的任意一个字符</p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#900050">[f-k]</font></font></span></p></td>
<td>
<p>匹配 "f"~"k" 之间的任意一个字母</p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#900050">[^A-F0-3]</font></font></span></p></td>
<td>
<p>匹配 "A"~"F","0"~"3" 之外的任意一个字符</p></td></tr></table>
<p>&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=[bcd][bcd]&amp;txt=abc123" target="_blank">举例1：表达式 "<span id="pattern" name="pattern"><font color="#000000"><font color="#900050">[bcd]</font><font color="#900050">[bcd]</font></font></span>" 匹配 "abc123" 时</a>，匹配的结果是：成功；匹配到的内容是："bc"；匹配到的位置是：开始于1，结束于3。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=%5B%5Eabc%5D&amp;txt=abc123" target="_blank">举例2：表达式 "<span id="pattern" name="pattern"><font color="#000000"><font color="#900050">[^abc]</font></font></span>" 匹配 "abc123" 时</a>，匹配的结果是：成功；匹配到的内容是："1"；匹配到的位置是：开始于3，结束于4。</p>
<hr color="#fea089" size="1" />

<h5><a name="times"></a>1.5 修饰匹配次数的特殊符号</h5>
<p>&nbsp;&nbsp;&nbsp; 前面章节中讲到的表达式，无论是只能匹配一种字符的表达式，还是可以匹配多种字符其中任意一个的表达式，都只能匹配一次。如果使用表达式再加上修饰匹配次数的特殊符号，那么不用重复书写表达式就可以重复匹配。<br /><br />&nbsp;&nbsp;&nbsp; 使用方法是："次数修饰"放在"被修饰的表达式"后边。比如："[bcd][bcd]" 可以写成 "[bcd]{2}"。</p>
<table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
<tr bgcolor="#f0f0f0">
<td width="67">
<p>表达式</p></td>
<td>
<p>作用</p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#e07000">{n}</font></font></span></p></td>
<td>
<p>表达式重复n次，比如：<a href="http://www.regexlab.com/zh/workshop.asp?pat=\w{2}&amp;txt=ab+c6" target="_blank">"\w{2}" 相当于 "\w\w"</a>；<a href="http://www.regexlab.com/zh/workshop.asp?pat=a{5}&amp;txt=bbaaaaaddee" target="_blank">"a{5}" 相当于 "aaaaa"</a></p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#e07000">{m,n}</font></font></span></p></td>
<td>
<p>表达式至少重复m次，最多重复n次，比如：<a href="http://www.regexlab.com/zh/workshop.asp?pat=ba{1,3}&amp;txt=a,baaa,baa,b,ba" target="_blank">"ba{1,3}"可以匹配 "ba"或"baa"或"baaa"</a></p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#e07000">{m,}</font></font></span></p></td>
<td>
<p>表达式至少重复m次，比如：<a href="http://www.regexlab.com/zh/workshop.asp?pat=\w\d{2,}&amp;txt=b1,a12,_456,_4AA,M12344,12346546547446534543543" target="_blank">"\w\d{2,}"可以匹配 "a12","_456","M12344"...</a></p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#e07000">?</font></font></span></p></td>
<td>
<p>匹配表达式0次或者1次，相当于 {0,1}，比如：<a href="http://www.regexlab.com/zh/workshop.asp?pat=a[cd]%3F&amp;txt=a,c,d,ac,ad" target="_blank">"a[cd]?"可以匹配 "a","ac","ad"</a></p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#e07000">+</font></font></span></p></td>
<td>
<p>表达式至少出现1次，相当于 {1,}，比如：<a href="http://www.regexlab.com/zh/workshop.asp?pat=a%2Bb&amp;txt=a%2Cb%2Cab%2Caab%2Caaab" target="_blank">"a+b"可以匹配 "ab","aab","aaab"...</a></p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#e07000">*</font></font></span></p></td>
<td>
<p>表达式不出现或出现任意次，相当于 {0,}，比如：<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5C%5E*b&amp;txt=%5E%2Cb%2C%5E%5E%5Eb%2C%5E%5E%5E%5E%5E%5E%5Eb" target="_blank">"\^*b"可以匹配 "b","^^^b"...</a></p></td></tr></table>
<p>&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=%5Cd%2B%5C.%3F%5Cd*&amp;txt=It%20costs%20%2412.5" target="_blank">举例1：表达式 "<span id="pattern" name="pattern"><font color="#000000"><font color="#900050">\d</font><font color="#e07000">+</font>\.<font color="#e07000">?</font><font color="#900050">\d</font><font color="#e07000">*</font></font></span>" 在匹配 "It costs $12.5" 时</a>，匹配的结果是：成功；匹配到的内容是："12.5"；匹配到的位置是：开始于10，结束于14。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=go{2,8}gle&amp;txt=Ads%20by%20goooooogle%2C%20or%20gooogle" target="_blank">举例2：表达式 "<span id="pattern" name="pattern"><font color="#000000">go<font color="#e07000">{2,8}</font>gle</font></span>" 在匹配 "Ads by goooooogle" 时</a>，匹配的结果是：成功；匹配到的内容是："goooooogle"；匹配到的位置是：开始于7，结束于17。</p>
<hr color="#fea089" size="1" />

<h5><a name="special"></a>1.6 其他一些代表抽象意义的特殊符号</h5>
<p>&nbsp;&nbsp;&nbsp; 一些符号在表达式中代表抽象的特殊意义：</p>
<table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
<tr bgcolor="#f0f0f0">
<td width="67">
<p>表达式</p></td>
<td>
<p>作用</p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#ff00ff">^</font></font></span></p></td>
<td>
<p>与字符串开始的地方匹配，不匹配任何字符</p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#ff00ff">$</font></font></span></p></td>
<td>
<p>与字符串结束的地方匹配，不匹配任何字符</p></td></tr>
<tr>
<td>
<p><span id="pattern" name="pattern"><font color="#000000"><font color="#ff00ff">\b</font></font></span></p></td>
<td>
<p>匹配一个单词边界，也就是单词和空格之间的位置，不匹配任何字符</p></td></tr></table>
<p>&nbsp;&nbsp;&nbsp; 进一步的文字说明仍然比较抽象，因此，举例帮助大家理解。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=^aaa&amp;txt=xxx+aaa+xxx" target="_blank">举例1：表达式 "<span id="pattern" name="pattern"><font color="#000000"><font color="#ff00ff">^</font>aaa</font></span>" 在匹配 "xxx aaa xxx" 时</a>，匹配结果是：失败。因为 "^" 要求与字符串开始的地方匹配，因此，只有当 "aaa" 位于字符串的开头的时候，"^aaa" 才能匹配，<a href="http://www.regexlab.com/zh/workshop.asp?pat=^aaa&amp;txt=aaa+xxx+xxx" target="_blank">比如："aaa xxx xxx"</a>。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=aaa$&amp;txt=xxx+aaa+xxx" target="_blank">举例2：表达式 "<span id="pattern" name="pattern"><font color="#000000">aaa<font color="#ff00ff">$</font></font></span>" 在匹配 "xxx aaa xxx" 时</a>，匹配结果是：失败。因为 "$" 要求与字符串结束的地方匹配，因此，只有当 "aaa" 位于字符串的结尾的时候，"aaa$" 才能匹配，<a href="http://www.regexlab.com/zh/workshop.asp?pat=aaa$&amp;txt=xxx+xxx+aaa" target="_blank">比如："xxx xxx aaa"</a>。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=.%5Cb.&amp;txt=@@@abc" target="_blank">举例3：表达式 "<span id="pattern" name="pattern"><font color="#000000"><font color="#900050">.</font><font color="#ff00ff">\b</font><font color="#900050">.</font></font></span>" 在匹配 "@@@abc" 时</a>，匹配结果是：成功；匹配到的内容是："@a"；匹配到的位置是：开始于2，结束于4。<br />&nbsp;&nbsp;&nbsp; 进一步说明："\b" 与 "^" 和 "$" 类似，本身不匹配任何字符，但是它要求它在匹配结果中所处位置的左右两边，其中一边是 "\w" 范围，另一边是 非"\w" 的范围。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=%5Cbend%5Cb&amp;txt=weekend,endfor,end" target="_blank">举例4：表达式 "<span id="pattern" name="pattern"><font color="#000000"><font color="#ff00ff">\b</font>end<font color="#ff00ff">\b</font></font></span>" 在匹配 "weekend,endfor,end" 时</a>，匹配结果是：成功；匹配到的内容是："end"；匹配到的位置是：开始于15，结束于18。</p>
<p>&nbsp;&nbsp;&nbsp; 一些符号可以影响表达式内部的子表达式之间的关系：</p>
<table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
<tr bgcolor="#f0f0f0">
<td width="65">
<p>表达式</p></td>
<td>
<p>作用</p></td></tr>
<tr>
<td>
<p>|</p></td>
<td>
<p>左右两边表达式之间 "或" 关系，匹配左边或者右边</p></td></tr>
<tr>
<td>
<p>( )</p></td>
<td>
<p>(1). 在被修饰匹配次数的时候，括号中的表达式可以作为整体被修饰<br />(2). 取匹配结果的时候，括号中的表达式匹配到的内容可以被单独得到</p></td></tr></table>
<p>&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=Tom%7CJack&amp;txt=I%27m+Tom%2C+he+is+Jack" target="_blank">举例5：表达式 "<span id="pattern" name="pattern"><font color="#000000">Tom<font color="#5050ff">|</font>Jack</font></span>" 在匹配字符串 "I'm Tom, he is Jack" 时</a>，匹配结果是：成功；匹配到的内容是："Tom"；匹配到的位置是：开始于4，结束于7。匹配下一个时，匹配结果是：成功；匹配到的内容是："Jack"；匹配到的位置时：开始于15，结束于19。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=%28go%5Cs*%29%2B&amp;txt=Let%27s%20go%20go%20go%21" target="_blank">举例6：表达式 "<span id="pattern" name="pattern"><font color="#000000"><font color="#5050ff">(</font>go<font color="#900050">\s</font><font color="#e07000">*</font><font color="#5050ff">)</font><font color="#e07000">+</font></font></span>" 在匹配 "Let's go go go!" 时</a>，匹配结果是：成功；匹配到内容是："go go go"；匹配到的位置是：开始于6，结束于14。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=%uFFE5%28%5Cd%2B%5C.%3F%5Cd*%29&amp;txt=%uFF0410.9%2C%uFFE520.5" target="_blank">举例7：表达式 "<span id="pattern" name="pattern"><font color="#000000">￥<font color="#5050ff">(</font><font color="#900050">\d</font><font color="#e07000">+</font>\.<font color="#e07000">?</font><font color="#900050">\d</font><font color="#e07000">*</font><font color="#5050ff">)</font></font></span>" 在匹配 "＄10.9,￥20.5" 时</a>，匹配的结果是：成功；匹配到的内容是："￥20.5"；匹配到的位置是：开始于6，结束于10。单独获取括号范围匹配到的内容是："20.5"。</p>
<hr color="#fea089" size="1" />

<h4>2. 正则表达式中的一些高级规则</h4>
<h5><a name="reluctant"></a>2.1 匹配次数中的贪婪与非贪婪</h5>
<p>&nbsp;&nbsp;&nbsp; 在使用修饰匹配次数的特殊符号时，有几种表示方法可以使同一个表达式能够匹配不同的次数，比如："{m,n}", "{m,}", "?", "*", "+"，具体匹配的次数随被匹配的字符串而定。这种重复匹配不定次数的表达式在匹配过程中，总是尽可能多的匹配。比如，针对文本 "dxxxdxxxd"，举例如下：</p>
<table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
<tr bgcolor="#f0f0f0">
<td width="93">
<p>表达式</p></td>
<td>
<p>匹配结果</p></td></tr>
<tr>
<td>
<p><a href="http://www.regexlab.com/zh/workshop.asp?pat=(d)(%5Cw%2B)&amp;txt=dxxxdxxxd" target="_blank"><span id="pattern" name="pattern"><font color="#000000"><font color="#5050ff">(</font>d<font color="#5050ff">)</font><font color="#5050ff">(</font><font color="#900050">\w</font><font color="#e07000">+</font><font color="#5050ff">)</font></font></span></a></p></td>
<td>
<p>"\w+" 将匹配第一个 "d" 之后的所有字符 "xxxdxxxd"</p></td></tr>
<tr>
<td>
<p><a href="http://www.regexlab.com/zh/workshop.asp?pat=(d)(%5Cw%2B)(d)&amp;txt=dxxxdxxxd" target="_blank"><span id="pattern" name="pattern"><font color="#000000"><font color="#5050ff">(</font>d<font color="#5050ff">)</font><font color="#5050ff">(</font><font color="#900050">\w</font><font color="#e07000">+</font><font color="#5050ff">)</font><font color="#5050ff">(</font>d<font color="#5050ff">)</font></font></span></a></p></td>
<td>
<p>"\w+" 将匹配第一个 "d" 和最后一个 "d" 之间的所有字符 "xxxdxxx"。虽然 "\w+" 也能够匹配上最后一个 "d"，但是为了使整个表达式匹配成功，"\w+" 可以 "让出" 它本来能够匹配的最后一个 "d"</p></td></tr></table>
<p>&nbsp;&nbsp;&nbsp; 由此可见，"\w+" 在匹配的时候，总是尽可能多的匹配符合它规则的字符。虽然第二个举例中，它没有匹配最后一个 "d"，但那也是为了让整个表达式能够匹配成功。同理，带 "*" 和 "{m,n}" 的表达式都是尽可能地多匹配，带 "?" 的表达式在可匹配可不匹配的时候，也是尽可能的 "要匹配"。这 种匹配原则就叫作 "贪婪" 模式 。</p>
<p>&nbsp;&nbsp;&nbsp; 非贪婪模式：<br /><br />&nbsp;&nbsp;&nbsp; 在修饰匹配次数的特殊符号后再加上一个 "?" 号，则可以使匹配次数不定的表达式尽可能少的匹配，使可匹配可不匹配的表达式，尽可能的 "不匹配"。这种匹配原则叫作 "非贪婪" 模式，也叫作 "勉强" 模式。如果少匹配就会导致整个表达式匹配失败的时候，与贪婪模式类似，非贪婪模式会最小限度的再匹配一些，以使整个表达式匹配成功。举例如下，针对文本 "dxxxdxxxd" 举例：</p>
<table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
<tr bgcolor="#f0f0f0">
<td width="93">
<p>表达式</p></td>
<td>
<p>匹配结果</p></td></tr>
<tr>
<td>
<p><a href="http://www.regexlab.com/zh/workshop.asp?pat=(d)(%5Cw%2B%3F)&amp;txt=dxxxdxxxd" target="_blank"><span id="pattern" name="pattern"><font color="#000000"><font color="#5050ff">(</font>d<font color="#5050ff">)</font><font color="#5050ff">(</font><font color="#900050">\w</font><font color="#e07000">+</font><font color="#e07000">?</font><font color="#5050ff">)</font></font></span></a></p></td>
<td>
<p>"\w+?" 将尽可能少的匹配第一个 "d" 之后的字符，结果是："\w+?" 只匹配了一个 "x"</p></td></tr>
<tr>
<td>
<p><a href="http://www.regexlab.com/zh/workshop.asp?pat=(d)(%5Cw%2B%3F)(d)&amp;txt=dxxxdxxxd" target="_blank"><span id="pattern" name="pattern"><font color="#000000"><font color="#5050ff">(</font>d<font color="#5050ff">)</font><font color="#5050ff">(</font><font color="#900050">\w</font><font color="#e07000">+</font><font color="#e07000">?</font><font color="#5050ff">)</font><font color="#5050ff">(</font>d<font color="#5050ff">)</font></font></span></a></p></td>
<td>
<p>为了让整个表达式匹配成功，"\w+?" 不得不匹配 "xxx" 才可以让后边的 "d" 匹配，从而使整个表达式匹配成功。因此，结果是："\w+?" 匹配 "xxx"</p></td></tr></table>
<p>&nbsp;&nbsp;&nbsp; 更多的情况，举例如下：<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=%3Ctd%3E%28%2E%2A%29%3C%2Ftd%3E&amp;txt=%3Ctd%3E%3Cp%3Eaa%3C%2Fp%3E%3C%2Ftd%3E%3Ctd%3E%3Cp%3Ebb%3C%2Fp%3E%3C%2Ftd%3E" target="_blank">举例1：表达式 "<span id="pattern" name="pattern"><font color="#000000">&lt;td&gt;<font color="#5050ff">(</font><font color="#900050">.</font><font color="#e07000">*</font><font color="#5050ff">)</font>&lt;/td&gt;</font></span>" 与字符串 "&lt;td&gt;&lt;p&gt;aa&lt;/p&gt;&lt;/td&gt; &lt;td&gt;&lt;p&gt;bb&lt;/p&gt;&lt;/td&gt;" 匹配时</a>，匹配的结果是：成功；匹配到的内容是 "&lt;td&gt;&lt;p&gt;aa&lt;/p&gt;&lt;/td&gt; &lt;td&gt;&lt;p&gt;bb&lt;/p&gt;&lt;/td&gt;" 整个字符串， 表达式中的 "&lt;/td&gt;" 将与字符串中最后一个 "&lt;/td&gt;" 匹配。 <br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=%3Ctd%3E%28%2E%2A%3F%29%3C%2Ftd%3E&amp;txt=%3Ctd%3E%3Cp%3Eaa%3C%2Fp%3E%3C%2Ftd%3E%3Ctd%3E%3Cp%3Ebb%3C%2Fp%3E%3C%2Ftd%3E" target="_blank">举例2：相比之下，表达式 "<span id="pattern" name="pattern"><font color="#000000">&lt;td&gt;<font color="#5050ff">(</font><font color="#900050">.</font><font color="#e07000">*</font><font color="#e07000">?</font><font color="#5050ff">)</font>&lt;/td&gt;</font></span>" 匹配举例1中同样的字符串时</a>，将只得到 "&lt;td&gt;&lt;p&gt;aa&lt;/p&gt;&lt;/td&gt;"， 再次匹配下一个时，可以得到第二个 "&lt;td&gt;&lt;p&gt;bb&lt;/p&gt;&lt;/td&gt;"。</p>
<hr color="#fea089" size="1" />

<h5><a name="backref"></a>2.2 反向引用 \1, \2...</h5>
<p>&nbsp;&nbsp;&nbsp; 表达式在匹配时，表达式引擎会将小括号 "( )" 包含的表达式所匹配到的字符串记录下来。在获取匹配结果的时候，小括号包含的表达式所匹配到的字符串可以单独获取。这一点，在前面的举例中，已经多次展示了。在实际应用场合中，当用某种边界来查找，而所要获取的内容又不包含边界时，必须使用小括号来指定所要的范围。比如前面的 "<span id="pattern" name="pattern"><font color="#000000">&lt;td&gt;<font color="#5050ff">(</font><font color="#900050">.</font><font color="#e07000">*</font><font color="#e07000">?</font><font color="#5050ff">)</font>&lt;/td&gt;</font></span>"。<br /><br />&nbsp;&nbsp;&nbsp; 其实，"小括号包含的表达式所匹配到的字符串" 不仅是在匹配结束后才可以使用，在匹配过程中也可以使用。表达式后边的部分，可以引用前面 "括号内的子匹配已经匹配到的字符串"。引用方法是 "\" 加上一个数字。"\1" 引用第1对括号内匹配到的字符串，"\2" 引用第2对括号内匹配到的字符串&#8230;&#8230;以此类推，如果一对括号内包含另一对括号，则外层的括号先排序号。换句话说，哪一对的左括号 "(" 在前，那这一对就先排序号。</p>
<p>&nbsp;&nbsp;&nbsp; 举例如下：<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=%28%27%7C%22%29%28%2E%2A%3F%29%28%5C1%29&amp;txt=%27Hello%27%2C+%22World%22" target="_blank">举例1：表达式 "<span id="pattern" name="pattern"><font color="#000000"><font color="#5050ff">(</font>'<font color="#5050ff">|</font>"<font color="#5050ff">)</font><font color="#5050ff">(</font><font color="#900050">.</font><font color="#e07000">*</font><font color="#e07000">?</font><font color="#5050ff">)</font><font color="#5050ff">(</font><font color="#ff00ff">\1</font><font color="#5050ff">)</font></font></span>" 在匹配 " 'Hello', "World" " 时</a>，匹配结果是：成功；匹配到的内容是：" 'Hello' "。再次匹配下一个时，可以匹配到 " "World" "。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=%28%5Cw%29%5C1%7B4%2C%7D&amp;txt=aa%20bbbb%20abcdefg%20ccccc%20111121111%20999999999" target="_blank">举例2：表达式 "<span id="pattern" name="pattern"><font color="#000000"><font color="#5050ff">(</font><font color="#900050">\w</font><font color="#5050ff">)</font><font color="#ff00ff">\1</font><font color="#e07000">{4,}</font></font></span>" 在匹配 "aa bbbb abcdefg ccccc 111121111 999999999" 时</a>，匹配结果是：成功；匹配到的内容是 "ccccc"。再次匹配下一个时，将得到 999999999。这个表达式要求 "\w" 范围的字符至少重复5次，<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5Cw%7B5%2C%7D&amp;txt=aa%20bbbb%20abcdefg%20ccccc%20111121111%20999999999" target="_blank">注意与 "\w{5,}" 之间的区别</a>。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=%3C%28%5Cw%2B%29%5Cs%2A%28%5Cw%2B%28%3D%28%27%7C%22%29%2E%2A%3F%5C4%29%3F%5Cs%2A%29%2A%3E%2E%2A%3F%3C%2F%5C1%3E&amp;txt=%3Ctd+id%3D%27td1%27+style%3D%22bgcolor%3Awhite%22%3E%3C%2Ftd%3E%0D%0A%3Cbody+onload%3D%22doit%28%29%22%3E%3C%2Fbody%3E" target="_blank">举例3：表达式 "<span id="pattern" name="pattern"><font color="#000000">&lt;<font color="#5050ff">(</font><font color="#900050">\w</font><font color="#e07000">+</font><font color="#5050ff">)</font><font color="#900050">\s</font><font color="#e07000">*</font><font color="#5050ff">(</font><font color="#900050">\w</font><font color="#e07000">+</font><font color="#5050ff">(</font>=<font color="#5050ff">(</font>'<font color="#5050ff">|</font>"<font color="#5050ff">)</font><font color="#900050">.</font><font color="#e07000">*</font><font color="#e07000">?</font><font color="#ff00ff">\4</font><font color="#5050ff">)</font><font color="#e07000">?</font><font color="#900050">\s</font><font color="#e07000">*</font><font color="#5050ff">)</font><font color="#e07000">*</font>&gt;<font color="#900050">.</font><font color="#e07000">*</font><font color="#e07000">?</font>&lt;/<font color="#ff00ff">\1</font>&gt;</font></span>" 在匹配 "&lt;td id='td1' style="bgcolor:white"&gt;&lt;/td&gt;" 时</a>，匹配结果是成功。如果 "&lt;td&gt;" 与 "&lt;/td&gt;" 不配对，则会匹配失败；如果改成其他配对，也可以匹配成功。</p>
<hr color="#fea089" size="1" />

<h5><a name="forward"></a>2.3 预搜索，不匹配；反向预搜索，不匹配</h5>
<p>&nbsp;&nbsp;&nbsp; 前面的章节中，我讲到了几个代表抽象意义的特殊符号："^"，"$"，"\b"。它们都有一个共同点，那就是：它们本身不匹配任何字符，只是对 "字符串的两头" 或者 "字符之间的缝隙" 附加了一个条件。理解到这个概念以后，本节将继续介绍另外一种对 "两头" 或者 "缝隙" 附加条件的，更加灵活的表示方法。</p>
<p>&nbsp;&nbsp;&nbsp; 正向预搜索："(?=xxxxx)"，"(?!xxxxx)"<br /><br />&nbsp;&nbsp;&nbsp; 格式："(?=xxxxx)"，在被匹配的字符串中，它对所处的 "缝隙" 或者 "两头" 附加的条件是：所在缝隙的右侧，必须能够匹配上 xxxxx 这部分的表达式。因为它只是在此作为这个缝隙上附加的条件，所以它并不影响后边的表达式去真正匹配这个缝隙之后的字符。这就类似 "\b"，本身不匹配任何字符。"\b" 只是将所在缝隙之前、之后的字符取来进行了一下判断，不会影响后边的表达式来真正的匹配。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=Windows+%28%3F%3DNT%7CXP%29&amp;txt=Windows+98%2C+Windows+NT%2C+Windows+2000" target="_blank">举例1：表达式 "<span id="pattern" name="pattern"><font color="#000000">Windows <font color="#999999">(?=</font>NT<font color="#5050ff">|</font>XP<font color="#999999">)</font></font></span>" 在匹配 "Windows 98, Windows NT, Windows 2000" 时</a>，将只匹配 "Windows NT" 中的 "Windows "，其他的 "Windows " 字样则不被匹配。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=%28%5Cw%29%28%28%3F%3D%5C1%5C1%5C1%29%28%5C1%29%29%2B&amp;txt=aaa+ffffff+999999999" target="_blank">举例2：表达式 "<span id="pattern" name="pattern"><font color="#000000"><font color="#5050ff">(</font><font color="#900050">\w</font><font color="#5050ff">)</font><font color="#5050ff">(</font><font color="#999999">(?=</font><font color="#ff00ff">\1</font><font color="#ff00ff">\1</font><font color="#ff00ff">\1</font><font color="#999999">)</font><font color="#5050ff">(</font><font color="#ff00ff">\1</font><font color="#5050ff">)</font><font color="#5050ff">)</font><font color="#e07000">+</font></font></span>" 在匹配字符串 "aaa ffffff 999999999" 时</a>，将可以匹配6个"f"的前4个，可以匹配9个"9"的前7个。这个表达式可以读解成：重复4次以上的字母数字，则匹配其剩下最后2位之前的部分。当然，这个表达式可以不这样写，在此的目的是作为演示之用。</p>
<p>&nbsp;&nbsp;&nbsp; 格式："(?!xxxxx)"，所在缝隙的右侧，必须不能匹配 xxxxx 这部分表达式。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=%28%28%3F%21%5Cbstop%5Cb%29%2E%29%2B&amp;txt=fdjka+ljfdl+stop+fjdsla+fdj" target="_blank">举例3：表达式 "<span id="pattern" name="pattern"><font color="#000000"><font color="#5050ff">(</font><font color="#999999">(?!</font><font color="#ff00ff">\b</font>stop<font color="#ff00ff">\b</font><font color="#999999">)</font><font color="#900050">.</font><font color="#5050ff">)</font><font color="#e07000">+</font></font></span>" 在匹配 "fdjka ljfdl stop fjdsla fdj" 时</a>，将从头一直匹配到 "stop" 之前的位置，如果字符串中没有 "stop"，则匹配整个字符串。<br /><br />&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=do%28%3F%21%5Cw%29&amp;txt=done%2C+do%2C+dog" target="_blank">举例4：表达式 "<span id="pattern" name="pattern"><font color="#000000">do<font color="#999999">(?!</font><font color="#900050">\w</font><font color="#999999">)</font></font></span>" 在匹配字符串 "done, do, dog" 时</a>，只能匹配 "do"。在本条举例中，"do" 后边使用 "(?!\w)" 和使用 "\b" 效果是一样的。</p>
<p>&nbsp;&nbsp;&nbsp; 反向预搜索："(?&lt;=xxxxx)"，"(?&lt;!xxxxx)"<br /><br />&nbsp;&nbsp;&nbsp; 这两种格式的概念和正向预搜索是类似的，反向预搜索要求的条件是：所在缝隙的 "左侧"，两种格式分别要求必须能够匹配和必须不能够匹配指定表达式，而不是去判断右侧。与 "正向预搜索" 一样的是：它们都是对所在缝隙的一种附加条件，本身都不匹配任何字符。<br /><br />&nbsp;&nbsp;&nbsp; 举例5：表达式 "<span id="pattern" name="pattern"><font color="#000000"><font color="#999999">(?&lt;=</font><font color="#900050">\d</font><font color="#e07000">{4}</font><font color="#999999">)</font><font color="#900050">\d</font><font color="#e07000">+</font><font color="#999999">(?=</font><font color="#900050">\d</font><font color="#e07000">{4}</font><font color="#999999">)</font></font></span>" 在匹配 "1234567890123456" 时，将匹配除了前4个数字和后4个数字之外的中间8个数字。由于 JScript.RegExp 不支持反向预搜索，因此，本条举例不能够进行演示。很多其他的引擎可以支持反向预搜索，比如：Java 1.4 以上的 java.util.regex 包，.NET 中System.Text.RegularExpressions 命名空间，以及本站推荐的<a href="http://www.regexlab.com/zh/deelx/" target="_blank">最简单易用的 DEELX 正则引擎</a>。</p>
<hr color="#fea089" size="1" />

<h4><a name="othercommon"></a>3. 其他通用规则</h4>
<p>&nbsp;&nbsp;&nbsp; 还有一些在各个正则表达式引擎之间比较通用的规则，在前面的讲解过程中没有提到。</p>
<p>3.1 表达式中，可以使用 "\xXX" 和 "\uXXXX" 表示一个字符（"X" 表示一个十六进制数）</p>
<table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
<tr bgcolor="#f0f0f0">
<td width="63">
<p>形式</p></td>
<td>
<p>字符范围</p></td></tr>
<tr>
<td>
<p>\xXX</p></td>
<td>
<p>编号在 0 ~ 255 范围的字符，比如：<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5Cx20&amp;txt=It+is%2E" target="_blank">空格可以使用 "\x20" 表示</a></p></td></tr>
<tr>
<td>
<p>\uXXXX</p></td>
<td>
<p>任何字符可以使用 "\u" 再加上其编号的4位十六进制数表示，比如：<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5Cu4E2D&amp;txt=%D6%D0%B9%FA" target="_blank">"\u4E2D"</a></p></td></tr></table>
<p>3.2 在表达式 "\s"，"\d"，"\w"，"\b" 表示特殊意义的同时，对应的大写字母表示相反的意义</p>
<table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
<tr bgcolor="#f0f0f0">
<td width="55">
<p>表达式</p></td>
<td>
<p>可匹配</p></td></tr>
<tr>
<td>
<p>\S</p></td>
<td>
<p><a href="http://www.regexlab.com/zh/workshop.asp?pat=%5CS%2B&amp;txt=abc+123+%40%23%24%25" target="_blank">匹配所有非空白字符（"\s" 可匹配各个空白字符）</a></p></td></tr>
<tr>
<td>
<p>\D</p></td>
<td>
<p><a href="http://www.regexlab.com/zh/workshop.asp?pat=%5CD%2B&amp;txt=abc+123+%40%23%24%25" target="_blank">匹配所有的非数字字符</a></p></td></tr>
<tr>
<td>
<p>\W</p></td>
<td>
<p><a href="http://www.regexlab.com/zh/workshop.asp?pat=%5CW%2B&amp;txt=abc+123+%40%23%24%25" target="_blank">匹配所有的字母、数字、下划线以外的字符</a></p></td></tr>
<tr>
<td>
<p>\B</p></td>
<td>
<p><a href="http://www.regexlab.com/zh/workshop.asp?pat=%5CB%2E%5CB&amp;txt=abc+123+%40%23%24%25" target="_blank">匹配非单词边界，即左右两边都是 "\w" 范围或者左右两边都不是 "\w" 范围时的字符缝隙</a></p></td></tr></table>
<p>3.3 在表达式中有特殊意义，需要添加 "\" 才能匹配该字符本身的字符汇总</p>
<table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
<tr bgcolor="#f0f0f0">
<td width="55">
<p>字符</p></td>
<td>
<p>说明</p></td></tr>
<tr>
<td>
<p>^</p></td>
<td>
<p>匹配输入字符串的开始位置。要匹配 "^" 字符本身，请使用 "\^"</p></td></tr>
<tr>
<td>
<p>$</p></td>
<td>
<p>匹配输入字符串的结尾位置。要匹配 "$" 字符本身，请使用 "\$"</p></td></tr>
<tr>
<td>
<p>( )</p></td>
<td>
<p>标记一个子表达式的开始和结束位置。要匹配小括号，请使用 "\(" 和 "\)"</p></td></tr>
<tr>
<td>
<p>[ ]</p></td>
<td>
<p>用来自定义能够匹配 '多种字符' 的表达式。要匹配中括号，请使用 "\[" 和 "\]"</p></td></tr>
<tr>
<td>
<p>{ }</p></td>
<td>
<p>修饰匹配次数的符号。要匹配大括号，请使用 "\{" 和 "\}"</p></td></tr>
<tr>
<td>
<p>.</p></td>
<td>
<p>匹配除了换行符（\n）以外的任意一个字符。要匹配小数点本身，请使用 "\."</p></td></tr>
<tr>
<td>
<p>?</p></td>
<td>
<p>修饰匹配次数为 0 次或 1 次。要匹配 "?" 字符本身，请使用 "\?"</p></td></tr>
<tr>
<td>
<p>+</p></td>
<td>
<p>修饰匹配次数为至少 1 次。要匹配 "+" 字符本身，请使用 "\+"</p></td></tr>
<tr>
<td>
<p>*</p></td>
<td>
<p>修饰匹配次数为 0 次或任意次。要匹配 "*" 字符本身，请使用 "\*"</p></td></tr>
<tr>
<td>
<p>|</p></td>
<td>
<p>左右两边表达式之间 "或" 关系。匹配 "|" 本身，请使用 "\|"</p></td></tr></table>
<p>3.4 括号 "( )" 内的子表达式，如果希望匹配结果不进行记录供以后使用，可以使用 "(?:xxxxx)" 格式</p>
<p>&nbsp;&nbsp;&nbsp; <a href="http://www.regexlab.com/zh/workshop.asp?pat=%28%3F%3A%28%5Cw%29%5C1%29%2B&amp;txt=a bbccdd efg" target="_blank">举例1：表达式 "<span id="pattern" name="pattern"><font color="#000000"><font color="#999999">(?:</font><font color="#5050ff">(</font><font color="#900050">\w</font><font color="#5050ff">)</font><font color="#ff00ff">\1</font><font color="#999999">)</font><font color="#e07000">+</font></font></span>" 匹配 "a bbccdd efg" 时</a>，结果是 "bbccdd"。括号 "(?:)" 范围的匹配结果不进行记录，因此 "(\w)" 使用 "\1" 来引用。</p>
<p>3.5 常用的表达式属性设置简介：Ignorecase，Singleline，Multiline，Global</p>
<table style="border-collapse: collapse" cellspacing="0" cellpadding="3" bgcolor="#f8f8f8" border="1">
<tr bgcolor="#f0f0f0">
<td width="80">
<p>表达式属性</p></td>
<td>
<p>说明</p></td></tr>
<tr>
<td>
<p>Ignorecase</p></td>
<td>
<p>默认情况下，表达式中的字母是要区分大小写的。配置为 Ignorecase 可使匹配时不区分大小写。有的表达式引擎，把 "大小写" 概念延伸至 UNICODE 范围的大小写。</p></td></tr>
<tr>
<td>
<p>Singleline</p></td>
<td>
<p>默认情况下，小数点 "." 匹配除了换行符（\n）以外的字符。配置为 Singleline 可使小数点可匹配包括换行符在内的所有字符。</p></td></tr>
<tr>
<td>
<p>Multiline</p></td>
<td>
<p>默认情况下，表达式 "^" 和 "$" 只匹配字符串的开始 &#9312; 和结尾 &#9315; 位置。如：<br /><br />&#9312;xxxxxxxxx&#9313;\n<br />&#9314;xxxxxxxxx&#9315;<br /><br />配置为 Multiline 可以使 "^" 匹配 &#9312; 外，还可以匹配换行符之后，下一行开始前 &#9314; 的位置，使 "$" 匹配 &#9315; 外，还可以匹配换行符之前，一行结束 &#9313; 的位置。</p></td></tr>
<tr>
<td>
<p>Global</p></td>
<td>
<p>主要在将表达式用来替换时起作用，配置为 Global 表示替换所有的匹配。</p></td></tr></table>
<p>
<hr color="#fea089" size="1" />

<p>&nbsp;</p>
<h4><a name="prompt"></a>4. 其他提示</h4>
<p>4.1 如果想要了解高级的正则引擎还支持那些复杂的正则语法，可参见<a href="http://www.regexlab.com/zh/deelx/syntax.htm" target="_blank">本站 DEELX 正则引擎的说明文档</a>。</p>
<p>4.2 如果要要求表达式所匹配的内容是整个字符串，而不是从字符串中找一部分，那么可以在表达式的首尾使用 "^" 和 "$"，比如："<span id="pattern" name="pattern"><font color="#000000"><font color="#ff00ff">^</font><font color="#900050">\d</font><font color="#e07000">+</font><font color="#ff00ff">$</font></font></span>" 要求整个字符串只有数字。</p>
<p>4.3 如果要求匹配的内容是一个完整的单词，而不会是单词的一部分，那么在表达式首尾使用 "\b"，比如：<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5Cb%28if%7Cwhile%7Celse%7Cvoid%7Cint%29%5Cb&amp;txt=if%28ifdo%29%0D%0A++++dosome%28%29%3B%0D%0Aelse%0D%0A++++doelse%28%29%3B" target="_blank">使用 "<span id="pattern" name="pattern"><font color="#000000"><font color="#ff00ff">\b</font><font color="#5050ff">(</font>if<font color="#5050ff">|</font>while<font color="#5050ff">|</font>else<font color="#5050ff">|</font>void<font color="#5050ff">|</font>int&#8230;&#8230;<font color="#5050ff">)</font><font color="#ff00ff">\b</font></font></span>" 来匹配程序中的关键字</a>。</p>
<p>4.4 表达式不要匹配空字符串。否则会一直得到匹配成功，而结果什么都没有匹配到。比如：准备写一个匹配 "123"、"123."、"123.5"、".5" 这几种形式的表达式时，整数、小数点、小数数字都可以省略，但是不要将表达式写成："<span id="pattern" name="pattern"><font color="#000000"><font color="#900050">\d</font><font color="#e07000">*</font>\.<font color="#e07000">?</font><font color="#900050">\d</font><font color="#e07000">*</font></font></span>"，因为如果什么都没有，这个表达式也可以匹配成功。<a href="http://www.regexlab.com/zh/workshop.asp?pat=%5Cd%2B%5C%2E%3F%5Cd%2A%7C%5C%2E%5Cd%2B&amp;txt=123%2C+123%2E%2C+123%2E5%2C+%2E5%2C+%2E" target="_blank">更好的写法是："<span id="pattern" name="pattern"><font color="#000000"><font color="#900050">\d</font><font color="#e07000">+</font>\.<font color="#e07000">?</font><font color="#900050">\d</font><font color="#e07000">*</font><font color="#5050ff">|</font>\.<font color="#900050">\d</font><font color="#e07000">+</font></font></span>"</a>。</p>
<p>4.5 能匹配空字符串的子匹配不要循环无限次。如果括号内的子表达式中的每一部分都可以匹配 0 次，而这个括号整体又可以匹配无限次，那么情况可能比上一条所说的更严重，匹配过程中可能死循环。虽然现在有些正则表达式引擎已经通过办法避免了这种情况出现死循环了，比如 .NET 的正则表达式，但是我们仍然应该尽量避免出现这种情况。如果我们在写表达式时遇到了死循环，也可以从这一点入手，查找一下是否是本条所说的原因。</p>
<p>4.6 合理选择贪婪模式与非贪婪模式，参见<a href="http://www.regexlab.com/zh/regtopic.htm#reluctant" target="_blank">话题讨论</a>。</p>
<p>4.7 或 "|" 的左右两边，对某个字符最好只有一边可以匹配，这样，不会因为 "|" 两边的表达式因为交换位置而有所不同。</p><img src="http://www.cnblogs.com/glacierh/aggbug/1653709.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/glacierh/archive/2010/01/21/1653709.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/glacierh/archive/2010/01/21/1653709.html#commentform" target="_blank">发表评论</a></p><p><a href="http://job.cnblogs.com/" target="_blank">找优秀程序员，就在博客园</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/59187/" target="_blank">Notifo推iPhone应用：弥补邮件推送缺陷</a><span style="color:gray">(2010-03-19 21:04)</span><br/>· <a href="http://news.cnblogs.com/n/59186/" target="_blank">分析：微软IE9现身 网络视频标准争议依旧未解</a><span style="color:gray">(2010-03-19 20:57)</span><br/>· <a href="http://news.cnblogs.com/n/59185/" target="_blank">连线朱骏：陈晓薇离开九城与魔兽无关</a><span style="color:gray">(2010-03-19 20:52)</span><br/>· <a href="http://news.cnblogs.com/n/59184/" target="_blank">九城总裁陈晓薇5月期满离任 朱骏将代理总裁</a><span style="color:gray">(2010-03-19 20:48)</span><br/>· <a href="http://news.cnblogs.com/n/59183/" target="_blank">Google携手Intel和Sony推出&quot;Google电视&quot;</a><span style="color:gray">(2010-03-19 20:44)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/59093/" target="_blank">[视频]想做你的Code</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>JavaScript--正则表达式</title><link>http://www.cnblogs.com/glacierh/archive/2009/12/26/1633024.html</link><dc:creator>Glacier</dc:creator><author>Glacier</author><pubDate>Sat, 26 Dec 2009 14:09:00 GMT</pubDate><guid>http://www.cnblogs.com/glacierh/archive/2009/12/26/1633024.html</guid><description><![CDATA[<p>阅读: 61 评论: 0 作者: <a href="http://www.cnblogs.com/glacierh/" target="_blank">Glacier</a> 发表于 2009-12-26 22:09 <a href="http://www.cnblogs.com/glacierh/archive/2009/12/26/1633024.html" target="_blank">原文链接</a></p><p>正则表达式(regular expression)对象包含一个正则表达式模式(pattern)。它具有用正则表达式模式去匹配或代替一个串(string)中特定字符(或字符集合)的属性(properties)和方法(methods)。</p>
<p>正则表达式构造函数： new RegExp("pattern"[,"flags"]);<br />参数说明：<br />pattern -- 一个正则表达式文本<br />flags -- 如果存在，将是以下值：<br />g: 全局匹配<br />i: 忽略大小写<br />gi: 以上组合</p>
<p>在构造函数中，一些特殊字符需要进行转意(在特殊字符前加"\")。正则表达式中的特殊字符：&nbsp;<br />\ 转意，即通常在"\"后面的字符不按原来意义解释，如/b/匹配字符"b"，当b前面加了反斜杆后/\b/，转意为匹配一个单词的边界。<br />-或-<br />对正则表达式功能字符的还原，如"*"匹配它前面元字符0次或多次，/a*/将匹配a,aa,aaa，加了"\"后，/a\*/ 将只匹配"a*"。&nbsp; <!--more-->^&nbsp; 匹配一个输入或一行的开头，/^a/匹配"an A"，而不匹配"An a"&nbsp;<br />$&nbsp; 匹配一个输入或一行的结尾，/a$/匹配"An a"，而不匹配"an A"&nbsp;<br />*&nbsp; 匹配前面元字符0次或多次，/ba*/将匹配b,ba,baa,baaa&nbsp;<br />+&nbsp; 匹配前面元字符1次或多次，/ba*/将匹配ba,baa,baaa&nbsp;<br />?&nbsp; 匹配前面元字符0次或1次，/ba*/将匹配b,ba&nbsp;<br />(x)&nbsp; 匹配x保存x在名为$1...$9的变量中&nbsp;<br />x|y&nbsp; 匹配x或y&nbsp;<br />{n}&nbsp; 精确匹配n次&nbsp;<br />{n,}&nbsp; 匹配n次以上&nbsp;<br />{n,m}&nbsp; 匹配n-m次&nbsp;<br />[xyz]&nbsp; 字符集(character set)，匹配这个集合中的任一一个字符(或元字符)&nbsp;<br />[^xyz]&nbsp; 不匹配这个集合中的任何一个字符&nbsp;<br />[\b]&nbsp; 匹配一个退格符<br />\b&nbsp; 匹配一个单词的边界&nbsp;<br />\B&nbsp; 匹配一个单词的非边界<br />\cX&nbsp; 这儿，X是一个控制符，/\cM/匹配Ctrl-M&nbsp;<br />\d&nbsp; 匹配一个字数字符，/\d/ = /[0-9]/&nbsp;<br />\D&nbsp; 匹配一个非字数字符，/\D/ = /[^0-9]/&nbsp;<br />\n&nbsp; 匹配一个换行符&nbsp;<br />\r&nbsp; 匹配一个回车符&nbsp;<br />\s&nbsp; 匹配一个空白字符，包括\n,\r,\f,\t,\v等&nbsp;<br />\S&nbsp; 匹配一个非空白字符，等于/[^\n\f\r\t\v]/&nbsp;<br />\t&nbsp; 匹配一个制表符&nbsp;<br />\v&nbsp; 匹配一个重直制表符&nbsp;<br />\w&nbsp; 匹配一个可以组成单词的字符(alphanumeric，这是我的意译，含数字)，包括下划线，如[\w]匹配"$5.98"中的5，等于[a-zA-Z0-9]&nbsp;<br />\W&nbsp; 匹配一个不可以组成单词的字符，如[\W]匹配"$5.98"中的$，等于[^a-zA-Z0-9]。</p>
<p>说了这么多了，我们来看一些正则表达式的实际应用的例子：<br />HTML代码的屏蔽<br />&nbsp;function mask_HTMLCode(strInput) {<br />&nbsp;&nbsp; var myReg = /&lt;(\w+)&gt;/;<br />&nbsp;&nbsp; return strInput.replace(myReg, "&amp;lt;$1&amp;gt;");<br />&nbsp;}<br />E-mail地址验证:<br />&nbsp;function test_email(strEmail) {<br />&nbsp; var myReg = /^[_a-z0-9]+@([_a-z0-9]+\.)+[a-z0-9]{2,3}$/;<br />&nbsp; if(myReg.test(strEmail)) return true;<br />&nbsp; return false;<br />&nbsp;}</p>
<p>正则表达式对象的属性及方法：<br />预定义的正则表达式拥有有以下静态属性：input, multiline, lastMatch, lastParen, leftContext,rightContext和$1到$9。其中input和multiline可以预设置。其他属性的值在执行过exec或 test方法后被根据不同条件赋以不同的值。许多属性同时拥有长和短(perl风格)的两个名字，并且，这两个名字指向同一个值。(</p>
<p>JavaScript模拟perl的正则表达式)<br />正则表达式对象的属性：<br />属性 含义<br />$1...$9 如果它(们)存在，是匹配到的子串&nbsp;<br />$_ 参见input&nbsp;<br />$* 参见multiline&nbsp;<br />$&amp; 参见lastMatch&nbsp;<br />$+ 参见lastParen&nbsp;<br />$` 参见leftContext&nbsp;<br />$''　　　　　　　　　 参见rightContext&nbsp;<br />constructor　　　&nbsp; 创建一个对象的一个特殊的函数原型&nbsp;<br />global　　　　　　&nbsp; 是否在整个串中匹配(bool型)&nbsp;<br />ignoreCase　　　　 匹配时是否忽略大小写(bool型)&nbsp;<br />input　　　　　　　 被匹配的串&nbsp;<br />lastIndex　　　　&nbsp; 最后一次匹配的索引&nbsp;<br />lastParen　　　　&nbsp; 最后一个括号括起来的子串&nbsp;<br />leftContext　　　&nbsp; 最近一次匹配以左的子串&nbsp;<br />multiline　　　　&nbsp; 是否进行多行匹配(bool型)&nbsp;<br />prototype　　　　&nbsp; 允许附加属性给对象&nbsp;<br />rightContext　　　 最近一次匹配以右的子串&nbsp;<br />source　　　　　　&nbsp; 正则表达式模式&nbsp;<br />lastIndex　　　　&nbsp; 最后一次匹配的索引&nbsp;</p>
<p>正则表达式对象的方法：<br />方法 含义<br />compile　　　　　&nbsp; 正则表达式比较&nbsp;<br />exec　　　　　　　 执行查找&nbsp;<br />test　　　　　　　 进行匹配&nbsp;<br />toSource　　　　　 返回特定对象的定义(literal</p>
<p>representing)，其值可用来创建一个新的对象。重载Object.toSource方法得到的。&nbsp;<br />toString　　　　　 返回特定对象的串。重载Object.toString方法得到的。&nbsp;<br />valueOf　　　　　&nbsp; 返回特定对象的原始值。重载Object.valueOf方法得到&nbsp;</p><pre class="javascript"><div class="head">例子</div><ol><li class="li1"><div class="de1">&lt;script language = <span class="st0">"JavaScript"</span>&gt; </div></li><li class="li1"><div class="de1"><span class="kw2">var</span> myReg = <span class="re0">/<span class="br0">(</span>w+<span class="br0">)</span>s<span class="br0">(</span>w+<span class="br0">)</span>/</span>; </div></li><li class="li1"><div class="de1"><span class="kw2">var</span> str  = <span class="st0">"John Smith"</span>; </div></li><li class="li1"><div class="de1"><span class="kw2">var</span> newstr = str.<span class="me1">replace</span><span class="br0">(</span>myReg, <span class="st0">"$2, $1"</span><span class="br0">)</span>; </div></li><li class="li1"><div class="de1">document.<span class="kw1">write</span><span class="br0">(</span>newstr<span class="br0">)</span>; </div></li><li class="li1"><div class="de1">&lt;/script&gt; </div></li><li class="li1"><div class="de1">将输出<span class="st0">"Smith, John"</span> <br /></div></li></ol><br /></pre>
<h1><strong><strong>常用的js正则表达式</strong></strong></h1>javascript验证表单时常用 <br /><br />"^-[0-9]*[1-9][0-9]*$"　　//负整数 <br /><br />"^-?\d+$"　　　　//整数 <br /><br />"^\d+(\.\d+)?$"　　//非负浮点数（正浮点数 + 0） <br /><br />"^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$"　　//正浮点数 <br /><br />"^((-\d+(\.\d+)?)|(0+(\.0+)?))$"　　//非正浮点数（负浮点数 + 0） <br /><br />"^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$"　　//负浮点数 <br /><br />"^(-?\d+)(\.\d+)?$"　　//浮点数 <br /><br />"^[A-Za-z]+$"　　//由26个英文字母组成的字符串 <br /><br />"^[A-Z]+$"　　//由26个英文字母的大写组成的字符串 <br /><br />"^[a-z]+$"　　//由26个英文字母的小写组成的字符串 <br /><br />"^[A-Za-z0-9]+$"　　//由数字和26个英文字母组成的字符串 <br /><br />"^\w+$"　　//由数字、26个英文字母或者下划线组成的字符串 <br /><br />"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$"　　　　//email地址 <br /><br />"^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$"　　//url<br /><br />
<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=879180</p><img src="http://www.cnblogs.com/glacierh/aggbug/1633024.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/glacierh/archive/2009/12/26/1633024.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/glacierh/archive/2009/12/26/1633024.html#commentform" target="_blank">发表评论</a></p><p><a href="http://job.cnblogs.com/" target="_blank">找优秀程序员，就在博客园</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/59187/" target="_blank">Notifo推iPhone应用：弥补邮件推送缺陷</a><span style="color:gray">(2010-03-19 21:04)</span><br/>· <a href="http://news.cnblogs.com/n/59186/" target="_blank">分析：微软IE9现身 网络视频标准争议依旧未解</a><span style="color:gray">(2010-03-19 20:57)</span><br/>· <a href="http://news.cnblogs.com/n/59185/" target="_blank">连线朱骏：陈晓薇离开九城与魔兽无关</a><span style="color:gray">(2010-03-19 20:52)</span><br/>· <a href="http://news.cnblogs.com/n/59184/" target="_blank">九城总裁陈晓薇5月期满离任 朱骏将代理总裁</a><span style="color:gray">(2010-03-19 20:48)</span><br/>· <a href="http://news.cnblogs.com/n/59183/" target="_blank">Google携手Intel和Sony推出&quot;Google电视&quot;</a><span style="color:gray">(2010-03-19 20:44)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/59093/" target="_blank">[视频]想做你的Code</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>解决VS2008 开发Windows Mobile 项目生成速度慢的问题（转）</title><link>http://www.cnblogs.com/glacierh/archive/2009/11/24/1609666.html</link><dc:creator>Glacier</dc:creator><author>Glacier</author><pubDate>Tue, 24 Nov 2009 09:08:00 GMT</pubDate><guid>http://www.cnblogs.com/glacierh/archive/2009/11/24/1609666.html</guid><description><![CDATA[<p>阅读: 93 评论: 0 作者: <a href="http://www.cnblogs.com/glacierh/" target="_blank">Glacier</a> 发表于 2009-11-24 17:08 <a href="http://www.cnblogs.com/glacierh/archive/2009/11/24/1609666.html" target="_blank">原文链接</a></p><span style="font-size: 13px; line-height: 19px; font-family: Verdana">&nbsp; 
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"><span style="font-family: 宋体">最近用</span><span lang="EN-US"><font face="Calibri">VS2008</font></span><span style="font-family: 宋体">开发</span><span lang="EN-US"><font face="Calibri">Windows Mobile</font></span><span style="font-family: 宋体">程序，使用C#、.NET Compact Framework，发现项目生成速度比较慢。用</span><span lang="EN-US"><font face="Calibri">VS2008</font></span><span style="font-family: 宋体">打开项目后，开始一段时间生成速度还能忍受，时间一长，编译速度巨慢，最慢达到</span><span lang="EN-US"><font face="Calibri">5</font></span><span style="font-family: 宋体">分钟之久，实在无法忍受。</span></p>
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"><span lang="EN-US"><O:P><font face="Calibri">&nbsp;</font></O:P></span></p>
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"><span style="font-family: 宋体">决定找出</span><span lang="EN-US"><font face="Calibri">VS2008</font></span><span style="font-family: 宋体">生成时，做了什么花费时间的工作。从工具</span><span lang="EN-US" style="font-family: Wingdings">&#224;</span><span style="font-family: 宋体">选项进入&#8220;选项&#8221;对话框<br /><br /></span><span style="font-family: 宋体"><br />选择&#8220;</span><span lang="EN-US"><font face="Calibri">MSBuild</font></span><span style="font-family: 宋体">项目生成输出详细信息&#8221;为&#8220;诊断&#8221;这样编译时，会输出具体执行了那些任务，花费了多少时间。</span></p>
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"><span lang="EN-US"><O:P><font face="Calibri">&nbsp;</font></O:P></span></p>
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"><span style="font-family: 宋体">结果发现最花费时间的是</span></p>
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"><span lang="EN-US"><font face="Calibri">Platform Verification Task</font></span></p>
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"><span lang="EN-US"><O:P><font face="Calibri">&nbsp;</font></O:P></span></p>
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"><span lang="EN-US"><a style="color: #336699; background-color: transparent; text-decoration: none" href="http://blogs.msdn.com/vsdteam/archive/2006/09/15/756400.aspx" target="_blank"><font face="Calibri" color="#0000ff">http://blogs.msdn.com/vsdteam/archive/2006/09/15/756400.aspx</font></a></span><span style="font-family: 宋体">有</span><span lang="EN-US"><font face="Calibri">Platform Verification Task</font></span></p>
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"><span style="font-family: 宋体">的具体描述</span></p>
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"><span lang="EN-US"><O:P><font face="Calibri">&nbsp;</font></O:P></span></p>
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"><span style="font-family: 宋体">参照上文的说明，修改文件<br /><br />C:\Windows\Microsoft.NET\Framework\v3.5\Microsoft.CompactFramework.Common.targets<br /><br />中<br /><br />&lt;Target<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Name="PlatformVerificationTask"&nbsp;<font color="#ff0000">Condition="'$(SkipPlatformVerification)' == 'true'"</font>&nbsp;&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;PlatformVerificationTask<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PlatformFamilyName="$(PlatformFamilyName)"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PlatformID="$(PlatformID)"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SourceAssembly="@(IntermediateAssembly)"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ReferencePath="@(ReferencePath)"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TreatWarningsAsErrors="$(TreatWarningsAsErrors)"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PlatformVersion="$(TargetFrameworkVersion)"/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/Target&gt;<br /><br />部分，红色文字为新增加的部分<br /></span></p>
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"></p>
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"><span lang="EN-US"><O:P><font face="Calibri">&nbsp;</font></O:P></span><span lang="EN-US"><O:P><font face="Calibri">&nbsp;</font></O:P></span></p>
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"><span lang="EN-US"><O:P><font face="Calibri">&nbsp;</font></O:P></span></p>
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"><span style="font-family: 宋体">于是项目生成速度大幅提高。</span></p>
<p class="MsoNormal" style="font-size: 13px; margin: 0px auto 10px; line-height: 150%"><font face="宋体"><br /></font></p>
<p><br /></p>
<p>引用于&nbsp;<a href="http://www.cnblogs.com/enjoyitzwg/archive/2008/10/23/1318304.html" target="_blank">http://www.cnblogs.com/enjoyitzwg/archive/2008/10/23/1318304.html</a>&nbsp;</span></p><img src="http://www.cnblogs.com/glacierh/aggbug/1609666.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/glacierh/archive/2009/11/24/1609666.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/glacierh/archive/2009/11/24/1609666.html#commentform" target="_blank">发表评论</a></p><p><a href="http://job.cnblogs.com/" target="_blank">找优秀程序员，就在博客园</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/59187/" target="_blank">Notifo推iPhone应用：弥补邮件推送缺陷</a><span style="color:gray">(2010-03-19 21:04)</span><br/>· <a href="http://news.cnblogs.com/n/59186/" target="_blank">分析：微软IE9现身 网络视频标准争议依旧未解</a><span style="color:gray">(2010-03-19 20:57)</span><br/>· <a href="http://news.cnblogs.com/n/59185/" target="_blank">连线朱骏：陈晓薇离开九城与魔兽无关</a><span style="color:gray">(2010-03-19 20:52)</span><br/>· <a href="http://news.cnblogs.com/n/59184/" target="_blank">九城总裁陈晓薇5月期满离任 朱骏将代理总裁</a><span style="color:gray">(2010-03-19 20:48)</span><br/>· <a href="http://news.cnblogs.com/n/59183/" target="_blank">Google携手Intel和Sony推出&quot;Google电视&quot;</a><span style="color:gray">(2010-03-19 20:44)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/59093/" target="_blank">[视频]想做你的Code</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>IIS Server Application Error 图文解决方法(转)</title><link>http://www.cnblogs.com/glacierh/archive/2009/11/24/1609568.html</link><dc:creator>Glacier</dc:creator><author>Glacier</author><pubDate>Tue, 24 Nov 2009 07:51:00 GMT</pubDate><guid>http://www.cnblogs.com/glacierh/archive/2009/11/24/1609568.html</guid><description><![CDATA[<p>阅读: 38 评论: 0 作者: <a href="http://www.cnblogs.com/glacierh/" target="_blank">Glacier</a> 发表于 2009-11-24 15:51 <a href="http://www.cnblogs.com/glacierh/archive/2009/11/24/1609568.html" target="_blank">原文链接</a></p><p>转自<a href="http://hi.baidu.com/76512/blog/item/2064fc245c42ca368744f94b.html" target="_blank">http://hi.baidu.com/76512/blog/item/2064fc245c42ca368744f94b.html</a></p>
<p>老郁闷，今天本来想继续把未完的ASP系统写完，本地浏览，出现了&#8220;常见错误&nbsp;&nbsp; 不能打开注册表关键字&#8221;等的提示，因为前两天是正常的，不可能是数据库连结语句出现问题，想着应该是IIS出错了。 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 于是，重启了IIS，问题依旧&#8230;&#8230;上网查找相关问题，好多同学重装了机器，这让我有点晕，不如重装IIS好了，控制面板中添加删除组件，再次安装，毛病更大了，出现了&#8220;Server Application Error&#8221;的提示，本来可以显示HTML页面的，现在统统成了：</p>
<p>Server Application Error<br />The server has encountered an error while loading an application during the processing of your request. Please refer to the event log for more detail information. Please contact the server administrator for assistance.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 网上教了一种方法可以解决这个问题，多是文字表述，搞得我2个多钟头才弄明白，还是掐几张图和大家共勉一下吧。</p>
<p>&nbsp;</p>
<p align="center" forimg="1"><img class="blogimg" alt="" src="http://hiphotos.baidu.com/76512/pic/item/ed19a2d3fa492021970a1616.jpg" border="0" small="0" /></p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在我的电脑上点鼠标右键，选择管理。</p>
<p align="left" forimg="1"><img class="blogimg" alt="" src="http://hiphotos.baidu.com/76512/pic/item/84fb1417dcdad8144a90a711.jpg" border="0" small="0" /></p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在计算机管理点事件查看器中的应用程序，如果你发现MSDTC错误的话，嘿嘿，也许你就不用象我这么麻烦了，其实要是我在重新安装IIS之前看一眼的话，我也不用麻烦了&#8230;&#8230;怪我水平高精尖的不算！双击错误提示，打开对话框：</p>
<div align="center" forimg="1"><img class="blogimg" alt="" src="http://hiphotos.baidu.com/76512/pic/item/42f09a520a7b131b0cf3e312.jpg" border="0" small="0" /></div>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 告诉俺这是缺少了一个日志文件，所以没启动成MSDTC服务，可以运行msdtc -resetlog来创建这个日志文件，鬼知道这MSDTC是什么服务，如果你这是这种情况，可以创建文件后启动MSDTC服务，试验一下ASP网页文件能否打开。我就没这么幸运，因为我自找的把麻烦升级了，看后文吧～</p>
<div align="center" forimg="1"><img class="blogimg" alt="" src="http://hiphotos.baidu.com/76512/pic/item/f91699130a25ab956538db1c.jpg" border="0" small="0" /></div>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在计算机管理点服务和应用程序中的服务，右侧就出现计算机的服务列表，出问题时你找不到&#8220;distributed transaction coordinator&#8221;这项服务的，嘿嘿，这是我启动MSDTC后才出现的服务，它的主要作用大家可以看上图中的描述部分，如何启动它，别急，先让我解决我的问题才说。</p>
<p align="left" forimg="1"><img class="blogimg" alt="" src="http://hiphotos.baidu.com/76512/pic/item/9ba506f4f7f0aafa7609d71e.jpg" border="0" small="0" /></p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在计算机管理点本地用户和组中的用户，右侧出现系统的用户列表，不好意思，我把我的用户名字马赛克了，我们要给IUSR_机器名和IWAM_机器名两个用户改密码，记得改成一样的密码。右键单击IUSR_机器名，菜单第一项就是更改密码，点击后：</p>
<p align="center" forimg="1"><img class="blogimg" alt="" src="http://hiphotos.baidu.com/76512/pic/item/08ae88269ba37f028a82a118.jpg" border="0" small="0" /></p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp; 当然是继续了，不能被这长篇大论给吓回去。</p>
<div align="center" forimg="1">
<div align="center" forimg="1"><img class="blogimg" alt="" src="http://hiphotos.baidu.com/76512/pic/item/45f311d5870ebcd151da4b18.jpg" border="0" small="0" /></div></div>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 密码设置成&#8220;123456&#8221;吧，用同样的方法给IWAM_机器名也设置一下。点击开始，运行，输入&#8220;CMD&#8221;回车。</p>
<div align="center" forimg="1"><img class="blogimg" alt="" src="http://hiphotos.baidu.com/76512/pic/item/fd0730f38be78845352acc19.jpg" border="0" small="0" /></div>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打开DOS窗口，输入&#8220;cd C:\Inetpub\AdminScripts&#8221;，大家可以根据系统安装盘符替换：</p>
<p align="center" forimg="1"><img class="blogimg" alt="" src="http://hiphotos.baidu.com/76512/pic/item/47f4ddcaeda96b53f21fe71b.jpg" border="0" small="0" /></p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 呵呵，下面是这个目录的文件列表，反正也不清楚都是做什么用的&#8230;&#8230;</p>
<p align="center" forimg="1"><img class="blogimg" alt="" src="http://hiphotos.baidu.com/76512/pic/item/11a8ae0f0d989af8ab64571b.jpg" border="0" small="0" /></p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接着输入&#8220;cscript.exe adsutil.vbs set w3svc/wamuserpass 123456&#8221;，你可以替换123456为你刚才在计算机管理处设置的密码，一定要一样的。</p>
<p align="center" forimg="1"><img class="blogimg" alt="" src="http://hiphotos.baidu.com/76512/pic/item/c6b6c113bd306836dd5401e5.jpg" border="0" small="0" /></p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 接着输入&#8220;cscript.exe adsutil.vbs set w3svc/anonymoususerpass 123456&#8221;，同样的，也要和上面设置的密码一样。</p>
<p align="center" forimg="1"><img class="blogimg" alt="" src="http://hiphotos.baidu.com/76512/pic/item/78fd888ba37bc9c6fd1f10e5.jpg" border="0" small="0" /></p>
<p align="left" forimg="1">出现上面图中的提示，说明设置密码成功了；再同步系统密码，我们输入：&#8220;cscript.exe synciwam.vbs -v&#8221;。</p>
<p align="center" forimg="1"><img class="blogimg" alt="" src="http://hiphotos.baidu.com/76512/pic/item/2b5e2f2d724c4921349bf7e7.jpg" border="0" small="0" /></p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 多数可能就此通过，系统正常了，但俺很不幸，最下边一行出现了&#8220;Error:8004E00F&#8221;的错误提示，本人这时候才知道是MSDTC没有正常启动的原因&#8230;&#8230;</p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 于是我在DOS窗口中输入&#8220;net stop msdtc&#8221;看是否启动了该项服务，出现下图状况：</p>
<p align="center" forimg="1"><img class="blogimg" alt="" src="http://hiphotos.baidu.com/76512/pic/item/20670633192c8aed1a4cffe1.jpg" border="0" small="0" /></p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说是系统没有启动MSDTC，俺先用&#8220;msdtc -uninstall&#8221;卸了它，再用&#8220;msdtc-install&#8221;重新装上，再用&#8220;msdtc -resetlog&#8221;创建日志文件，最后用&#8220;net start msdtc&#8221;启动服务，成功。同步系统密码吧，输入：&#8220;cscript.exe synciwam.vbs -v&#8221;再回车。 </p>
<p align="center" forimg="1"><img class="blogimg" alt="" src="http://hiphotos.baidu.com/76512/pic/item/8d5b1a38e5299ae7b211c7e3.jpg" border="0" small="0" /></p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 没错误，去试一下ASP页面是否能成功打开？也许你们的都可以了，可俺还是不行&#8230;&#8230;最后一招，注册相关组件。在DOS窗口，输入&#8220;cd windows\system32\inetsrv &#8221;，进入系统文件夹的inetsrv目录。</p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 然后输入&#8220;rundll32 wamreg.dll, CreateIISPackage&#8221; <br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最后输入&#8220;regsvr32 asptxn.dll &#8221;</p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可算是成了，两个钟头过去了&#8230;&#8230;给大家分享一下，同志们下次就用不着两钟头了，也许十几分钟就搞定～需要提醒的是，在DOS窗口输入完命令记得回车哦！</p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 网友甲：GHOST重装系统也不过5分钟！</p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 网友乙：这还用教？简单到死&#8230;&#8230;</p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 网友丙：还是没看明白！</p>
<p align="left" forimg="1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 本人很无语&#8230;&#8230;</p><img src="http://www.cnblogs.com/glacierh/aggbug/1609568.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/glacierh/archive/2009/11/24/1609568.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/glacierh/archive/2009/11/24/1609568.html#commentform" target="_blank">发表评论</a></p><p><a href="http://job.cnblogs.com/" target="_blank">找优秀程序员，就在博客园</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/59187/" target="_blank">Notifo推iPhone应用：弥补邮件推送缺陷</a><span style="color:gray">(2010-03-19 21:04)</span><br/>· <a href="http://news.cnblogs.com/n/59186/" target="_blank">分析：微软IE9现身 网络视频标准争议依旧未解</a><span style="color:gray">(2010-03-19 20:57)</span><br/>· <a href="http://news.cnblogs.com/n/59185/" target="_blank">连线朱骏：陈晓薇离开九城与魔兽无关</a><span style="color:gray">(2010-03-19 20:52)</span><br/>· <a href="http://news.cnblogs.com/n/59184/" target="_blank">九城总裁陈晓薇5月期满离任 朱骏将代理总裁</a><span style="color:gray">(2010-03-19 20:48)</span><br/>· <a href="http://news.cnblogs.com/n/59183/" target="_blank">Google携手Intel和Sony推出&quot;Google电视&quot;</a><span style="color:gray">(2010-03-19 20:44)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/59093/" target="_blank">[视频]想做你的Code</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>正则表达式</title><link>http://www.cnblogs.com/glacierh/archive/2009/11/17/1604833.html</link><dc:creator>Glacier</dc:creator><author>Glacier</author><pubDate>Tue, 17 Nov 2009 10:58:00 GMT</pubDate><guid>http://www.cnblogs.com/glacierh/archive/2009/11/17/1604833.html</guid><description><![CDATA[<p>阅读: 67 评论: 0 作者: <a href="http://www.cnblogs.com/glacierh/" target="_blank">Glacier</a> 发表于 2009-11-17 18:58 <a href="http://www.cnblogs.com/glacierh/archive/2009/11/17/1604833.html" target="_blank">原文链接</a></p><table style="table-layout: fixed; width: 100%">
<tr>
<td>
<div class="cnt" id="blog_text"><strong>1、正则表达式简介<br /><br /></strong>　　正则表达式提供了功能强大、灵活而又高效的方法来处理文本。正则表达式的全面模式匹配表示法可以快速地分析大量的文本以找到特定的字符模式；提取、编辑、替换或删除文本子字符串；或将提取的字符串添加到集合以生成报告。对于处理字符串（例如&nbsp;HTML&nbsp;处理、日志文件分析和&nbsp;HTTP&nbsp;标头分析）的许多应用程序而言，正则表达式是不可缺少的工具。&nbsp;<br /><br />　　.NET&nbsp;框架正则表达式并入了其他正则表达式实现的最常见功能，被设计为与&nbsp;Perl&nbsp;5&nbsp;正则表达式兼容，.NET&nbsp;框架正则表达式还包括一些在其他实现中尚未提供的功能，.NET&nbsp;框架正则表达式类是基类库的一部分，并且可以和面向公共语言运行库的任何语言或工具一起使用。<br /><br />　　<strong>2、字符串搜索</strong><br /><br />　　正则表达式语言由两种基本字符类型组成：原义（正常）文本字符和元字符。正是元字符组为正则表达式提供了处理能力。当前，所有的文本编辑器都有一些搜索功能，通常可以打开一个对话框，在其中的一个文本框中键入要定位的字符串，如果还要同时进行替换操作，可以键入一个替换字符串，比如在Windows操作系统中的记事本、Office系列中的文档编辑器都有这种功能。这种搜索最简单的方式，这类问题很容易用String类的String.Replace()方法来解决，但如果需要在文档中识别某个重复的，该怎么办？编写一个例程，从一个String类中选择重复的字是比较复杂的，此时使用语言就很适合。<br /><br />　　一般表达式语言是一种可以编写搜索表达式的语言。在该语言中，可以把文档中要搜索的文本、转义序列和特定含义的其他字符组合在一起，例如序列\b表示一个字的开头和结尾（子的边界），如果要表示正在查找的以字符th开头的字，就可以编写一般表达式\bth（即序列字符界是-t-h）。如果要搜索所有以th结尾的字，就可以编写th\b（序列t-h-字边界）。但是，一般表达式要比这复杂得多，例如，可以在搜索操作中找到存储部分文本的工具性程序（facility）。<br /><br />　　<strong>3、.NET&nbsp;框架的正则表达式类</strong><br /><br />　　下面通过介绍&nbsp;.NET&nbsp;框架的正则表达式类，熟悉一下.NET框架下的正则表达式的使用方法。<br /><br />　　3.1&nbsp;Regex&nbsp;类表示只读正则表达式<br /><br />　　Regex&nbsp;类包含各种静态方法，允许在不显式实例化其他类的对象的情况下使用其他正则表达式类。以下代码示例创建了&nbsp;Regex&nbsp;类的实例并在<a class="bluekey" href="http://www.yesky.com/key/1942/201942.html" target="_blank">初始化</a>对象时定义一个简单的正则表达式。请注意，使用了附加的反斜杠作为转义字符，它将&nbsp;\s&nbsp;匹配字符类中的反斜杠指定为原义字符。<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>Regex&nbsp;r;&nbsp;//&nbsp;声明一个&nbsp;Regex类的变量<br />r&nbsp;=&nbsp;new&nbsp;Regex("\\s2000");&nbsp;//&nbsp;定义表达式</td></tr></table><br />　　3.2&nbsp;Match&nbsp;类表示正则表达式匹配操作的结果<br /><br />　　以下示例使用&nbsp;Regex&nbsp;类的&nbsp;Match&nbsp;方法返回&nbsp;Match&nbsp;类型的对象，以便找到输入字符串中第一个匹配。此示例使用&nbsp;Match&nbsp;类的&nbsp;Match.Success&nbsp;属性来指示是否已找到匹配。<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>Regex&nbsp;r&nbsp;=&nbsp;new&nbsp;Regex("abc");&nbsp;//&nbsp;定义一个Regex对象实例<br />Match&nbsp;m&nbsp;=&nbsp;r.Match("123abc456");&nbsp;//&nbsp;在字符串中匹配<br />if&nbsp;(m.Success)&nbsp;<br />{<br />　Console.WriteLine("Found&nbsp;match&nbsp;at&nbsp;position&nbsp;"&nbsp;+&nbsp;m.Index);&nbsp;//输入匹配字符的位置<br />}</td></tr></table><br />　　3.3&nbsp;MatchCollection&nbsp;类表示非重叠匹配的序列<br /><br />　　该集合为只读的，并且没有公共<a class="bluekey" href="http://www.yesky.com/key/3379/193379.html" target="_blank">构造函数</a>。MatchCollection&nbsp;的实例是由&nbsp;Regex.Matches&nbsp;属性返回的。使用&nbsp;Regex&nbsp;类的&nbsp;Matches&nbsp;方法，通过在输入字符串中找到的所有匹配填充&nbsp;MatchCollection。下面代码示例演示了如何将集合复制到一个字符串数组（保留每一匹配）和一个整数数组（指示每一匹配的位置）中。<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>MatchCollection&nbsp;mc;<br />String[]&nbsp;results&nbsp;=&nbsp;new&nbsp;String[20];<br />int[]&nbsp;matchposition&nbsp;=&nbsp;new&nbsp;int[20];<br />Regex&nbsp;r&nbsp;=&nbsp;new&nbsp;Regex("abc");&nbsp;//定义一个Regex对象实例<br />mc&nbsp;=&nbsp;r.Matches("123abc4abcd");&nbsp;<br />for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;mc.Count;&nbsp;i++)&nbsp;//在输入字符串中找到所有匹配<br />{<br />　results[i]&nbsp;=&nbsp;mc[i].Value;&nbsp;//将匹配的字符串添在字符串数组中<br />　matchposition[i]&nbsp;=&nbsp;mc[i].Index;&nbsp;//记录匹配字符的位置<br />}</td></tr></table><br />　　3.4&nbsp;GroupCollection&nbsp;类表示捕获的组的集合<br /><br />　　该集合为只读的，并且没有公共构造函数。GroupCollection&nbsp;的实例在&nbsp;Match.Groups&nbsp;属性返回的集合中返回。下面的<a class="bluekey" href="http://www.yesky.com/key/627/195627.html" target="_blank">控制台</a>应用程序查找并输出由正则表达式捕获的组的数目。&nbsp;<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>using&nbsp;System;<br />using&nbsp;System.Text.RegularExpressions;<br />public&nbsp;class&nbsp;RegexTest&nbsp;<br />{<br />　public&nbsp;static&nbsp;void&nbsp;RunTest()&nbsp;<br />　{<br />　　Regex&nbsp;r&nbsp;=&nbsp;new&nbsp;Regex("(a(b))c");&nbsp;//定义组<br />　　Match&nbsp;m&nbsp;=&nbsp;r.Match("abdabc");<br />　　Console.WriteLine("Number&nbsp;of&nbsp;groups&nbsp;found&nbsp;=&nbsp;"&nbsp;+&nbsp;m.Groups.Count);<br />　}<br />　public&nbsp;static&nbsp;void&nbsp;Main()&nbsp;<br />　{<br />　　RunTest();<br />　}<br />}</td></tr></table><br />　　该示例产生下面的输出：<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>Number&nbsp;of&nbsp;groups&nbsp;found&nbsp;=&nbsp;3</td></tr></table><br />　　3.5&nbsp;CaptureCollection&nbsp;类表示捕获的子字符串的序列&nbsp;<br /><br />　　由于限定符，捕获组可以在单个匹配中捕获多个字符串。Captures属性（CaptureCollection&nbsp;类的对象）是作为&nbsp;Match&nbsp;和&nbsp;group&nbsp;类的成员提供的，以便于对捕获的子字符串的集合的访问。例如，如果使用正则表达式&nbsp;((a(b))c)+（其中&nbsp;+&nbsp;限定符指定一个或多个匹配）从字符串"abcabcabc"中捕获匹配，则子字符串的每一匹配的&nbsp;Group&nbsp;的&nbsp;CaptureCollection&nbsp;将包含三个成员。<br /><br />　　下面的程序使用正则表达式&nbsp;(Abc)+来查找字符串"XYZAbcAbcAbcXYZAbcAb"中的一个或多个匹配，阐释了使用&nbsp;Captures&nbsp;属性来返回多组捕获的子字符串。&nbsp;<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>using&nbsp;System;<br />using&nbsp;System.Text.RegularExpressions;<br />public&nbsp;class&nbsp;RegexTest&nbsp;<br />{<br />　public&nbsp;static&nbsp;void&nbsp;RunTest()&nbsp;<br />　{<br />　　int&nbsp;counter;<br />　　Match&nbsp;m;<br />　　CaptureCollection&nbsp;cc;<br />　　GroupCollection&nbsp;gc;<br />　　Regex&nbsp;r&nbsp;=&nbsp;new&nbsp;Regex("(Abc)+");&nbsp;//查找"Abc"<br />　　m&nbsp;=&nbsp;r.Match("XYZAbcAbcAbcXYZAbcAb");&nbsp;//设定要查找的字符串<br />　　gc&nbsp;=&nbsp;m.Groups;<br />　　//输出查找组的数目<br />　　Console.WriteLine("Captured&nbsp;groups&nbsp;=&nbsp;"&nbsp;+&nbsp;gc.Count.<a class="bluekey" href="http://www.yesky.com/key/2245/207245.html" target="_blank">ToString</a>());&nbsp;<br />　　//&nbsp;Loop&nbsp;through&nbsp;each&nbsp;group.<br />　　for&nbsp;(int&nbsp;i=0;&nbsp;i&nbsp;&lt;&nbsp;gc.Count;&nbsp;i++)&nbsp;//查找每一个组<br />　　{<br />　　　cc&nbsp;=&nbsp;gc[i].Captures;<br />　　　counter&nbsp;=&nbsp;cc.Count;<br />　　　Console.WriteLine("Captures&nbsp;count&nbsp;=&nbsp;"&nbsp;+&nbsp;counter.ToString());<br />　　　for&nbsp;(int&nbsp;ii&nbsp;=&nbsp;0;&nbsp;ii&nbsp;&lt;&nbsp;counter;&nbsp;ii++)&nbsp;<br />　　　{<br />　　　　//&nbsp;Print&nbsp;capture&nbsp;and&nbsp;position.<br />　　　　Console.WriteLine(cc[ii]&nbsp;+&nbsp;"&nbsp;Starts&nbsp;at&nbsp;character&nbsp;"&nbsp;+&nbsp;<br />　　　　cc[ii].Index);&nbsp;//输入捕获位置<br />　　　}<br />　　}<br />　}<br />　public&nbsp;static&nbsp;void&nbsp;Main()&nbsp;{<br />　　RunTest();<br />　}<br />}</td></tr></table><br />　　此例返回下面的输出结果：<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>Captured&nbsp;groups&nbsp;=&nbsp;2<br />Captures&nbsp;count&nbsp;=&nbsp;1<br />AbcAbcAbc&nbsp;Starts&nbsp;at&nbsp;character&nbsp;3<br />Captures&nbsp;count&nbsp;=&nbsp;3<br />Abc&nbsp;Starts&nbsp;at&nbsp;character&nbsp;3<br />Abc&nbsp;Starts&nbsp;at&nbsp;character&nbsp;6<br />Abc&nbsp;Starts&nbsp;at&nbsp;character&nbsp;9</td></tr></table><br />　　3.6&nbsp;Capture&nbsp;类包含来自单个子表达式捕获的结果<br /><br />　　在&nbsp;Group&nbsp;集合中循环，从&nbsp;Group&nbsp;的每一成员中提取&nbsp;Capture&nbsp;集合，并且将变量&nbsp;posn&nbsp;和&nbsp;length&nbsp;分别分配给找到每一字符串的初始字符串中的字符位置，以及每一字符串的长度。<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>Regex&nbsp;r;<br />Match&nbsp;m;<br />CaptureCollection&nbsp;cc;<br />int&nbsp;posn,&nbsp;length;<br />r&nbsp;=&nbsp;new&nbsp;Regex("(abc)*");<br />m&nbsp;=&nbsp;r.Match("bcabcabc");<br />for&nbsp;(int&nbsp;i=0;&nbsp;m.Groups[i].Value&nbsp;!=&nbsp;"";&nbsp;i++)&nbsp;<br />{<br />　cc&nbsp;=&nbsp;m.Groups[i].Captures;&nbsp;<br />　for&nbsp;(int&nbsp;j&nbsp;=&nbsp;0;&nbsp;j&nbsp;&lt;&nbsp;cc.Count;&nbsp;j++)&nbsp;<br />　{<br />　　posn&nbsp;=&nbsp;cc[j].Index;&nbsp;//捕获对象位置<br />　　length&nbsp;=&nbsp;cc[j].Length;&nbsp;//捕获对象长度<br />　}<br />}</td></tr></table><br />
<table width="90%" align="center" border="0">
<tr>
<td>
<div align="center"><img src="http://www.yesky.com/imagelist/05/07/2t56od94p521.jpg" border="0"  alt="" /><br />图1：对象关系</div></td></tr></table><br />　　把组合字符组合起来后，每次都会返回一个组对象，就可能并不是我们希望的结果。如果希望把组合字符作为搜索模式的一部分，就会有相当大的系统开销。对于单个的组，可以用以字符序列"?:"开头的组禁止这么做，就像<a class="bluekey" href="http://www.yesky.com/key/2849/177849.html" target="_blank">URI</a>样例那样。而对于所有的组，可以在RegEx.Matches()方法上指定RegExOptions.ExplicitCapture标志。<br /><br />　　<strong>4、利用正则表达式实现字符串搜索<br /></strong><br />　　4.1&nbsp;在C#中使用.NET一般表达式引擎<br /><br />　　下面将通过一个样例的开发，执行并显示一些搜索的结果，说明一般表达式的一些特性，以及如何在C#中使用.NET一般表达式引擎。说明使用字符串时应在前面加上符号@。<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>String&nbsp;Text=@"I&nbsp;can&nbsp;not&nbsp;find&nbsp;my&nbsp;position&nbsp;in&nbsp;Beijing";</td></tr></table><br />　　把这个文本称为输入字符串，为了说明一般表达式.NET类，本文先进行一次纯文本的搜索，这次搜索不带任何转义序列或一般表达式命令。假定要查找所有字符串ion，把这个搜索字符串称为模式。使用一般表达式和上面声明的变量Text，编写出下面的代码：<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>String&nbsp;Pattern&nbsp;=&nbsp;"ion";<br />MatchCollection&nbsp;Matches&nbsp;=&nbsp;Regex.Matches(Text,Pattern,RegexOptions);<br />foreach(Match&nbsp;NextMatch&nbsp;in&nbsp;Matches)<br />{&nbsp;Console.WriteLine(NextMatch.Index);&nbsp;}</td></tr></table><br />　　在这段代码中，使用了System.Text.RegularExpressions名称空间中Regex类的静态方法Match()。这个方法的参数是一些输入文本、一个模式和RegexOptions每句中的一组可选标志。Matches()返回MatchCollection，每个匹配都用一个Match对象来表示。在上面的代码中，只是在集合中迭代，使用Match类的Index属性，返回输入文本中匹配所在的索引。运行这段代码，将得到1个匹配项。<br /><br />　　一般集合的功能主要取决于模式字符串。原因是模式字符串不仅仅包含纯文本。如前所述。还包含元字符和转义序列，元字符是给出命令的特殊字符，而转义序列的工作方式与C#的转义序列相同，它们都是以反斜杠\开头的字符，具有特殊的含义。例如，假定要查找以n开头的字，就可以使用转义序列\b，它表示一个字的边界（字的边界是以某个字母数字标的字符开头，或者后面是一个空白字符或标点符号），下面编写如下代码：&nbsp;<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>String&nbsp;Pattern&nbsp;=&nbsp;@"\bn";<br />MatchCollection&nbsp;Matches&nbsp;=&nbsp;Regex.Matches(Text,Pattern,RegexOptions.IgnoreCase|<br />RegexOptions.ExplicitCapture);</td></tr></table><br />　　要在运行时把\b传递给.NET一般表达式引擎，反斜杠\不应被C#编译器解释为转义序列。如果要查找以序列ion结尾的字，可以使用下面的代码：<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>String&nbsp;Pattern&nbsp;=&nbsp;@"ion\b";</td></tr></table><br />　　如果要查找以字母n开头，以序列ion结尾的所有字，需要一个以\bn开头，以ion\b结尾的模式，中间内容怎么办？需要告诉计算机n和ion中间的内容可以是任意长度的字符，只要字符不是空白即可，正确的模式如下所示：<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>String&nbsp;Pattern&nbsp;=&nbsp;@"\bn\S*ion\b";</td></tr></table><br />　　4.2&nbsp;特定字符或转义序列<br /><br />　　大多数重要的正则表达式语言运算符都是非转义的单个字符。转义符&nbsp;\（单个反斜杠）通知正则表达式分析器反斜杠后面的字符不是运算符。例如，分析器将星号&nbsp;(*)&nbsp;视为重复限定符，而将后跟星号的反斜杠&nbsp;(\*)&nbsp;视为&nbsp;Unicode&nbsp;字符&nbsp;002A。<br /><br />　　使用一般表达式要习惯的一点是，查看像这样怪异的字符序列，但这个序列的工作是非常逻辑化的。转义序列\S表示任何不适空白的字符。*称为数量词，其含义是前面的字符可以重复任意次，包括0次。序列\S*表示任何不适空白的字符。因此，上面的模式匹配于以n开头，以ion结尾的任何单个字。下表中列出的字符转义在正则表达式和替换模式中都会被识别。<br /><br />　　表1：特定字符或转义序列<br /><br />
<table cellspacing="0" cellpadding="2" width="90%" align="center" border="1">
<tr>
<td>特定字符或转义序列</td>
<td>含义</td>
<td>样例&nbsp;</td>
<td>匹配的样例</td></tr>
<tr>
<td>^&nbsp;</td>
<td>输入文本的开头</td>
<td>^B&nbsp;</td>
<td>B，但只能是文本中的第一个字符</td></tr>
<tr>
<td>$&nbsp;</td>
<td>输入文本的结尾</td>
<td>X$</td>
<td>X，但只能是文本中的最后一个字符</td></tr>
<tr>
<td>.&nbsp;</td>
<td>除了换行字符（\n）以外的所有单个字符</td>
<td>i.ation</td>
<td>isation、ization</td></tr>
<tr>
<td>*&nbsp;</td>
<td>可以重复0次或多次的前导字符</td>
<td>ra*t</td>
<td>rat、raat等</td></tr>
<tr>
<td>+&nbsp;</td>
<td>可以重复1次或多次的前导字符</td>
<td>ra+t</td>
<td>rt、rat、raat等</td></tr>
<tr>
<td>？</td>
<td>可以重复0次或1次的前导字符</td>
<td>ra?t&nbsp;</td>
<td>只有rt和rat匹配</td></tr>
<tr>
<td>\s&nbsp;</td>
<td>任何空白字符&nbsp;</td>
<td>\sa&nbsp;</td>
<td>[space]a,\ta,\na（\t和\n与C#的\t和\n含义相同）</td></tr>
<tr>
<td>\S&nbsp;</td>
<td>任何不是空白的字符</td>
<td>\SF</td>
<td>aF,rF,cF，但不能是\tf</td></tr>
<tr>
<td>\b&nbsp;</td>
<td>字边界</td>
<td>ion\b</td>
<td>以ion结尾的任何字</td></tr>
<tr>
<td>\B&nbsp;</td>
<td>不是字边界的位置&nbsp;</td>
<td>\BX\B&nbsp;</td>
<td>字中间的任何X</td></tr></table><br />　　如果要搜索一个元字符，也可以通过带有反斜杠的转义字符来表示。例如，.表示除了换行字符以外的任何字符，而\.表示一个点。<br />可以把可替换的字符放在方括号中，请求匹配包含这些字符。例如，[1|c]表示字符可以是1或者是c。如果要搜索map或者man，可以使用序列"ma[n|p]"（仅指引号内字符，下面雷同）。在方括号中，也可以制定一个范围，例如"[a-z]"表示所有的小写字母（使用连字号&nbsp;(-)&nbsp;允许指定连续字符范围），"[B-F]"表示B到F之间的所有大写字母，"[0-9]"表示一个数字，如果要搜索一个整数（该序列只包含0到9的字符），就可以编写"[0-9]+"（注意，使用+字符表示至少要有这样一个数字，但可以有多个数字，所以9、83和3443等都是匹配的。）<br />下面看看一般表达式的结果，编写一个实例RegularExpressionsZzy。建立几个一般表达式，显示其结果，让用户了解一下表达式是如何工作的。<br /><br />　　该实例的核心是一个方法WriteMatches()，它把MatchCollection中的所有匹配以比较详细的方式显示出来。对于每个匹配，它都会显示该匹配在输入字符串中所在的索引，匹配的字符串和一个略长的字符串，其中包含输入文本中至多8个外围字符，其中至少有5个字符放在匹配的前面，至多5个字符放在匹配的后面（如果匹配的位置在输入文本的开头或结尾5个字符内，则结果中匹配前后的字符就会少于4个）。换言之，靠近输入文本末尾的匹配应是"and&nbsp;messaging&nbsp;ofd"，匹配的前后各有5个字符，但位于输入文本的最后一个字上的匹配就应是"g&nbsp;of&nbsp;data"，匹配的字后只有一个字符。因为在该字符的后面是字符串的结尾。这个长字符串可以更清楚地表明一般表达式是在什么地方查找到匹配的：<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>static&nbsp;void&nbsp;WriteMatches(string&nbsp;text,&nbsp;MatchCollection&nbsp;matches)<br />{<br />　Console.WriteLine("Original&nbsp;text&nbsp;was:&nbsp;\n\n"&nbsp;+&nbsp;text&nbsp;+&nbsp;"\n");<br />　Console.WriteLine("No.&nbsp;of&nbsp;matches:&nbsp;"&nbsp;+&nbsp;matches.Count);<br />　foreach&nbsp;(Match&nbsp;nextMatch&nbsp;in&nbsp;matches)<br />　{<br />　　int&nbsp;Index&nbsp;=&nbsp;nextMatch.Index;<br />　　string&nbsp;result&nbsp;=&nbsp;nextMatch.ToString();<br />　　int&nbsp;charsBefore&nbsp;=&nbsp;(Index&nbsp;&lt;&nbsp;5)&nbsp;?&nbsp;Index&nbsp;:&nbsp;5;<br />　　int&nbsp;fromEnd&nbsp;=&nbsp;text.Length&nbsp;-&nbsp;Index&nbsp;-&nbsp;result.Length;<br />　　int&nbsp;charsAfter&nbsp;=&nbsp;(fromEnd&nbsp;&lt;&nbsp;5)&nbsp;?&nbsp;fromEnd&nbsp;:&nbsp;5;<br />　　int&nbsp;charsToDisplay&nbsp;=&nbsp;charsBefore&nbsp;+&nbsp;charsAfter&nbsp;+&nbsp;result.Length;<br />　　Console.WriteLine("Index:&nbsp;{0},&nbsp;\tString:&nbsp;{1},&nbsp;\t{2}",Index,&nbsp;result,&nbsp;<br />　　text.Substring(Index&nbsp;-&nbsp;charsBefore,&nbsp;charsToDisplay));<br />　}<br />}</td></tr></table><br />　　在这个方法中，处理过程是确定在较长的字符串中有多少个字符可以显示，而无需超限输入文本的开头或结尾。注意在Match对象上使用了另一个属性Value，它包含标识该匹配的字符串，而且，RegularExpressionsZzy只包含名为Find_po，Find_n等的方法，这些方法根据本文执行某些搜索操作。<br /><br />　　4.3&nbsp;正则表达式选项<br /><br />　　可以使用影响匹配行为的选项修改正则表达式模式。可以通过两种基本方法设置正则表达式选项：其一是可以在&nbsp;Regex(pattern,&nbsp;options)&nbsp;构造函数中的&nbsp;options&nbsp;参数中指定，其中&nbsp;options&nbsp;是&nbsp;RegexOptions&nbsp;枚举值的按位"或"组合；其二是使用内联&nbsp;(?imnsx-imnsx:)&nbsp;分组构造或&nbsp;(?imnsx-imnsx)&nbsp;其他构造在正则表达式模式内设置它们。<br /><br />　　在内联选项构造中，一个选项或一组选项前面的减号&nbsp;(-)&nbsp;用于关闭这些选项。例如，内联构造&nbsp;(?ix-ms)&nbsp;将打开&nbsp;IgnoreCase&nbsp;和&nbsp;IgnorePatternWhiteSpace&nbsp;选项而关闭&nbsp;Multiline&nbsp;和&nbsp;Singleline&nbsp;选项。<br /><br />　　表2：RegexOptions&nbsp;枚举的成员以及等效的内联选项字符<br /><br />
<table cellspacing="0" cellpadding="2" width="90%" align="center" border="1">
<tr>
<td>RegexOption&nbsp;成员</td>
<td>内联字符</td>
<td>说明</td></tr>
<tr>
<td>None&nbsp;</td>
<td>无&nbsp;</td>
<td>指定不设置任何选项。</td></tr>
<tr>
<td>IgnoreCase</td>
<td>i&nbsp;</td>
<td>指定不区分大小写的匹配。</td></tr>
<tr>
<td>Multiline</td>
<td>m&nbsp;</td>
<td>指定多行模式。更改&nbsp;^&nbsp;和&nbsp;$&nbsp;的含义，以使它们分别与任何行的开头和结尾匹配，而不只是与整个字符串的开头和结尾匹配。</td></tr>
<tr>
<td>ExplicitCapture</td>
<td>n&nbsp;</td>
<td>指定唯一有效的捕获是显式命名或编号的&nbsp;(?&lt;name&gt;...)&nbsp;形式的组。这允许圆括号充当非捕获组，从而避免了由&nbsp;(?:...)&nbsp;导致的语法上的笨拙。</td></tr>
<tr>
<td>Compiled</td>
<td>无</td>
<td>指定正则表达式将被编译为程序集。生成该正则表达式的&nbsp;Microsoft&nbsp;中间语言&nbsp;(MSIL)&nbsp;代码；以较长的启动时间为代价，得到更快的执行速度。&nbsp;</td></tr>
<tr>
<td>Singleline</td>
<td>s&nbsp;</td>
<td>指定单行模式。更改句点字符&nbsp;(.)&nbsp;的含义，以使它与每个字符（而不是除&nbsp;\n&nbsp;外的所有字符）匹配。</td></tr>
<tr>
<td>IgnorePatternWhitespace</td>
<td>x&nbsp;</td>
<td>指定从模式中排除非转义空白并启用数字符号&nbsp;(#)&nbsp;后面的注释。请注意，空白永远不会从字符类中消除。</td></tr>
<tr>
<td>RightToLeft</td>
<td>无&nbsp;</td>
<td>指定搜索是从右向左而不是从左向右进行的。具有此选项的正则表达式将移动到起始位置的左边而不是右边。（因此，起始位置应指定为字符串的结尾而不是开头。）为了避免构造具有无限循环的正则表达式的可能性，此选项不能在中流指定。但是，(?&lt;)&nbsp;回顾后发构造提供了可用作子表达式的类似替代物。</td></tr>
<tr>
<td>ECMAScript&nbsp;</td>
<td>无&nbsp;</td>
<td>指定已为表达式启用了符合&nbsp;ECMAScript&nbsp;的行为。此选项仅可与&nbsp;IgnoreCase&nbsp;和&nbsp;Multiline&nbsp;标志一起使用。将&nbsp;ECMAScript&nbsp;同任何其他标志一起使用将导致异常。</td></tr></table><br />　　例如，Find_po在字开头处查找以"po"开头的字符串：<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>static&nbsp;void&nbsp;Find_po()<br />{<br />　string&nbsp;text&nbsp;=&nbsp;@"&nbsp;I&nbsp;can&nbsp;not&nbsp;find&nbsp;my&nbsp;position&nbsp;in&nbsp;Beijing&nbsp;";<br />　string&nbsp;pattern&nbsp;=&nbsp;@"\bpo\S*ion\b";<br />　MatchCollection&nbsp;matches&nbsp;=&nbsp;Regex.Matches(text,&nbsp;pattern,&nbsp;RegexOptions.IgnoreCase&nbsp;<br />|&nbsp;RegexOptions.IgnorePatternWhitespace&nbsp;|&nbsp;RegexOptions.ExplicitCapture);<br />　WriteMatches(text,&nbsp;matches);<br />}</td></tr></table><br />　　这段代码还使用了名称空间RegularExpressions：<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>using&nbsp;System;<br />using&nbsp;System.Text.RegularExpressions;</td></tr></table><br />　　4.4&nbsp;匹配、组和捕获<br /><br />　　一般表达式的一个很好的特性是可以把字符组合起来，方式与C#中的复合语句一样。在C#中，可以通过把任意数量的语句放在花括号中的方式把它们组合在一起。其结果就像一个复合语句那样。在一般表达式模式中，也可以把任何字符组合起来（包括元字符和转义序列），像处理一个字符那样处理它们。唯一的区别是要使用圆括号，而不是花括号，得到的序列成为一个组。&nbsp;<br /><br />　　例如，模式"(an)+"定位序列an的任以重复。量词+只应用于它前面的一个字符，但因为我们把字符组合起来了，所以它现在把重复的an作为一个单元来对待。"(an)."应用到输入文本"bananas&nbsp;came&nbsp;to&nbsp;Europe&nbsp;late&nbsp;in&nbsp;the&nbsp;annals&nbsp;of&nbsp;history"上，会从bananas中选择出anan。另一方面，如果使用an+，则将从annals中选择ann，从bananas中选择出两个an。为什么(an)+选择的是anan，而没有把单个的an作为一个匹配。匹配规则是不能重复的，如果有可能重复，在默认情况下就选择较长的匹配。<br /><br />　　但是，组的功能要比这强大得多。在默认情况下，把模式的一部分组合为一个组时，就要求一般表达式引擎记住可以按照这个组来匹配，也可以按照整个模式来匹配。换言之，可以把组当作一个要匹配的模式，如果要把字符串分解为各个部分，这种模式就是非常有效的。&nbsp;<br />例如，URI的格式是"&lt;protocol&gt;://&lt;address&gt;:&lt;port&gt;"，其中端口是可选的。它的一个样例是http://www.comprg.com.cn:8080。假定要从一个URI中提取协议、地址和端口，而且紧邻URI的后面可能有空白（但没有标点符号），就可以使用下面的表达式："\b(\S+)://(\S+)(?::(\S+))?\b"<br /><br />　　该表达式的工作方式如下：首先，前导和尾部的\b序列确保只需要考虑完全是字的文本部分，在这个文本部分中，第一组"(\S+)://"会选择一个或多个不适空白的字符，其后是"://"。在HTTPURI的开头会选择出http://。花括号表示把http存储为一个组。后面的"(\S+)"则在上述URI中选择www.&nbsp;comprg.com.cn，这个组在遇到词的结尾时或标记另一个组的冒号"(:)"时结束。<br /><br />　　下一个组选择端口（本例是:8080）。后面的？表示这个组在匹配中是可选的，如果没有:xxxx，也不会妨碍匹配的标记。<br /><br />　　这是非常重要的，因为端口在URI中一般不指定，实际上，在大多数情况下，URI是没有端口号的。但是，事情会比较复杂。如果要求冒号可以出现，也可以不出现，但不希望把这个冒号也存储在组中。为此，可以嵌套两个组：内部的"(\S+)"组选择冒号后面的内容（本例中是8080），外面的组包含内部的组，后面是一个冒号，该冒号又在序列"?:"的后面。这个序列表示该组不应保存（只需要保存"8080"，不需要保存":8080"）。不要把这两个冒号混淆了，第一个冒号是序列"?:"的一部分，表示不保存这个组，第二个冒号是要搜索的文本。<br /><br />　　在这个字符串上运行该模式：I&nbsp;always&nbsp;visit&nbsp;http://www.&nbsp;comprg.com.cn&nbsp;得到的匹配是http://www.&nbsp;comprg.com.cn。在这个匹配中，仅提到了三个组，还有第四个组表示匹配本身。理论上，每个组都可以选择0次、1次或者多次匹配。单个的匹配就称为捕获。在第一个组"(\S+)"，有一个捕获http。第二个组也有一个捕获www.&nbsp;comprg.com.cn，但第三个组没有捕获，因为在这个URI中没有端口号。注意该字符串在其本身上包含第二个http://。虽然它匹配于第一个组，但不会被搜索出来，因为整个搜索表达式不匹配于这部分文本。<br />再比如下面这个例子，以下代码示例使用&nbsp;Match.Result&nbsp;来从&nbsp;URL提取协议和端口号。例如，"http://www.yahoo.com.cn:8080/index.html"将返回"http:8080"。<br /><br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e3e3e3" border="1">
<tr>
<td>String&nbsp;Extension(String&nbsp;url)&nbsp;<br />{<br />　Regex&nbsp;r&nbsp;=&nbsp;new&nbsp;Regex(@"^(?&lt;proto&gt;\w+)://[^/]+?(?&lt;port&gt;:\d+)?/",<br />　RegexOptions.Compiled);<br />　return&nbsp;r.Match(url).Result("${proto}${port}");&nbsp;<br />}</td></tr></table><br />　<strong>　5、小结</strong><br /><br />　　.NET&nbsp;框架正则表达式类是基类库的一部分，并且可以和面向公共语言运行库的任何语言或工具（包括&nbsp;ASP.NET&nbsp;和&nbsp;Visual&nbsp;Studio&nbsp;.NET）一起使用。本文给出了在C#下利用正则表达式实现字符串搜索功能的方法，通过对.NET框架下的正则表达式的研究及实例分析，总结了正则表达式的规则、选项等，方便以后朋友们的应用。</div></td></tr></table><img src="http://www.cnblogs.com/glacierh/aggbug/1604833.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/glacierh/archive/2009/11/17/1604833.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/glacierh/archive/2009/11/17/1604833.html#commentform" target="_blank">发表评论</a></p><p><a href="http://job.cnblogs.com/" target="_blank">找优秀程序员，就在博客园</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/59187/" target="_blank">Notifo推iPhone应用：弥补邮件推送缺陷</a><span style="color:gray">(2010-03-19 21:04)</span><br/>· <a href="http://news.cnblogs.com/n/59186/" target="_blank">分析：微软IE9现身 网络视频标准争议依旧未解</a><span style="color:gray">(2010-03-19 20:57)</span><br/>· <a href="http://news.cnblogs.com/n/59185/" target="_blank">连线朱骏：陈晓薇离开九城与魔兽无关</a><span style="color:gray">(2010-03-19 20:52)</span><br/>· <a href="http://news.cnblogs.com/n/59184/" target="_blank">九城总裁陈晓薇5月期满离任 朱骏将代理总裁</a><span style="color:gray">(2010-03-19 20:48)</span><br/>· <a href="http://news.cnblogs.com/n/59183/" target="_blank">Google携手Intel和Sony推出&quot;Google电视&quot;</a><span style="color:gray">(2010-03-19 20:44)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/59093/" target="_blank">[视频]想做你的Code</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>Effective C# 读书笔记（一）：C#语言元素</title><link>http://www.cnblogs.com/glacierh/archive/2009/08/16/1547060.html</link><dc:creator>Glacier</dc:creator><author>Glacier</author><pubDate>Sun, 16 Aug 2009 02:16:00 GMT</pubDate><guid>http://www.cnblogs.com/glacierh/archive/2009/08/16/1547060.html</guid><description><![CDATA[<p>阅读: 62 评论: 2 作者: <a href="http://www.cnblogs.com/glacierh/" target="_blank">Glacier</a> 发表于 2009-08-16 10:16 <a href="http://www.cnblogs.com/glacierh/archive/2009/08/16/1547060.html" target="_blank">原文链接</a></p>&nbsp; 
<p>1<span style="font-family: 宋体">、使用属性代替可访问的数据成员</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">只要打算将数据暴露在类型的公有接口或受保护的接口中，我们都应该使用属性来实现。对于具有序列或者字典特征的类型，则应该采用索引器。所有数据成员都应一律声明为私有。使用属性的好处显而易见：我们可以得到更好的数据绑定支持，我们可以更容易地在将来对其访问方法的实现做任何改变。将变量封装在属性中只不过增加几行代码。如果刚开始使用数据成员，后来又发现需要使用属性，这时再来修改的成本将是几个小时。今天投入一点，会为明天节省许多时间。</span></p>
<p style="text-indent: 21pt">JIT<span style="font-family: 宋体">编译器会对某些方法调用（包括属性访问器）进行内联处理，属性和数据成员的效率没有任何差别。及时属性访问器没有被内联，实际的效率差别相对于函数调用的成本来讲也是可以忽略不计的。只有在很少的情况下，这种差别才值得我们注意。</span></p>
<p>&nbsp;</p>
<p>2<span style="font-family: 宋体">、运行时常量（</span>readonly<span style="font-family: 宋体">）优于编译时常量（</span>const<span style="font-family: 宋体">）</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">在</span>c#<span style="font-family: 宋体">中，我们用</span>readonly<span style="font-family: 宋体">关键字声明运行时常量，用</span>const<span style="font-family: 宋体">关键字来声明编译时常量。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">编译时常量在编译后的结果代码中会被替换为该常量的值。运行时常量在运行时被计算，编译后代码将维持对</span>readonly<span style="font-family: 宋体">变量（而非它的值）的引用。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">编译时常量只可用于值类型，运行时常量则没有限制。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">使用</span>const<span style="font-family: 宋体">较之于使用</span>readonly<span style="font-family: 宋体">的唯一好处就是性能：使用已知常量值得代码效率要比访问</span>readonly<span style="font-family: 宋体">值的代码效率稍好一点，但是其中的效率提升是非常小的。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">只有当某些情况要求变量的值必须在编译时可用，才应该考虑使用</span>const<span style="font-family: 宋体">，例如：特性（</span>attribute<span style="font-family: 宋体">）类的参数，枚举定义，以及某些不随组件版本变化而变化的值。否则，对于其他任何情况，都应该优先选择</span>readonly<span style="font-family: 宋体">常量，从而获得其所具有的灵活性。</span></p>
<p>&nbsp;</p>
<p>3<span style="font-family: 宋体">、操作符</span>is<span style="font-family: 宋体">或</span>as<span style="font-family: 宋体">优于强制转型</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">好的面向对象实践对告诫我们避免转型，但有时候我们别无选择。不能避免转型时，我们应该尽量使用</span>as<span style="font-family: 宋体">和</span>is<span style="font-family: 宋体">操作符来清晰的表达意图。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">当我们要立即进行转型时，我们应使用</span>as<span style="font-family: 宋体">操作符。如果仅仅是进行类型的判断而不需要立即进行转型，使用</span>is<span style="font-family: 宋体">即可。</span></p>
<p>&nbsp;</p>
<p>4<span style="font-family: 宋体">、使用</span>Conditional<span style="font-family: 宋体">特性代替</span>#if<span style="font-family: 宋体">条件编译</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">使用</span>Conditional<span style="font-family: 宋体">特性比使用</span>#if/#endif<span style="font-family: 宋体">产生的</span>IL<span style="font-family: 宋体">代码更有效。同时，将其限制在函数层次上可以清晰的讲条件行代码分离出来，从而使我们的代码具有更好的机构。另外，</span>C#<span style="font-family: 宋体">编译器也为此提供了很好的支持，从而帮助我们避免以前使用</span>#if<span style="font-family: 宋体">或</span>#endif<span style="font-family: 宋体">时犯的错误。</span></p>
<p>&nbsp;</p>
<p>5<span style="font-family: 宋体">、总是提供</span>ToString<span style="font-family: 宋体">（）方法</span></p>
<p style="text-indent: 21pt">System.Object<span style="font-family: 宋体">默认提供的</span>ToString<span style="font-family: 宋体">（）方法会返回类型的名称。我们可以简单的重写</span>ToString<span style="font-family: 宋体">（）方法，来满足我们的要求。也可以提供重载的</span>ToString<span style="font-family: 宋体">（）方法，使用格式字符串来为我们的类型指定自己的格式，满足更复杂的需求。</span></p>
<p>&nbsp;</p>
<p>6<span style="font-family: 宋体">、优先采用</span>foreach<span style="font-family: 宋体">循环语句</span></p>
<p style="text-indent: 21pt">foreach<span style="font-family: 宋体">是一个非常有用的语句，它会使用最高效的构造为&#8220;数组的上下界索引&#8221;、&#8220;多维数组遍历&#8221;和&#8220;操作数转型&#8221;产生正确的代码，并且产生的是最具效率的循环结构。它是遍历集合的最佳方式。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">任何集合类型都可以使用</span>foreach<span style="font-family: 宋体">。有</span>3<span style="font-family: 宋体">种方法可以使一个类支持</span>foreach<span style="font-family: 宋体">方法：</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">（</span>1<span style="font-family: 宋体">）类型具备一个公有的</span>GetEnumerator()<span style="font-family: 宋体">方法；</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">（</span>2<span style="font-family: 宋体">）类型显示实现了</span>IEnumerable<span style="font-family: 宋体">接口；</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">（</span>3<span style="font-family: 宋体">）类型实现了</span>IEnumerator<span style="font-family: 宋体">接口。</span></p>  <img src="http://www.cnblogs.com/glacierh/aggbug/1547060.html?type=1" width="1" height="1" alt=""/><p>评论: 2　<a href="http://www.cnblogs.com/glacierh/archive/2009/08/16/1547060.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/glacierh/archive/2009/08/16/1547060.html#commentform" target="_blank">发表评论</a></p><p><a href="http://job.cnblogs.com/" target="_blank">找优秀程序员，就在博客园</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/59187/" target="_blank">Notifo推iPhone应用：弥补邮件推送缺陷</a><span style="color:gray">(2010-03-19 21:04)</span><br/>· <a href="http://news.cnblogs.com/n/59186/" target="_blank">分析：微软IE9现身 网络视频标准争议依旧未解</a><span style="color:gray">(2010-03-19 20:57)</span><br/>· <a href="http://news.cnblogs.com/n/59185/" target="_blank">连线朱骏：陈晓薇离开九城与魔兽无关</a><span style="color:gray">(2010-03-19 20:52)</span><br/>· <a href="http://news.cnblogs.com/n/59184/" target="_blank">九城总裁陈晓薇5月期满离任 朱骏将代理总裁</a><span style="color:gray">(2010-03-19 20:48)</span><br/>· <a href="http://news.cnblogs.com/n/59183/" target="_blank">Google携手Intel和Sony推出&quot;Google电视&quot;</a><span style="color:gray">(2010-03-19 20:44)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/59093/" target="_blank">[视频]想做你的Code</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>浅析c#中多态的实现（修正版）</title><link>http://www.cnblogs.com/glacierh/archive/2009/07/19/1526670.html</link><dc:creator>Glacier</dc:creator><author>Glacier</author><pubDate>Sun, 19 Jul 2009 13:05:00 GMT</pubDate><guid>http://www.cnblogs.com/glacierh/archive/2009/07/19/1526670.html</guid><description><![CDATA[<p>阅读: 146 评论: 1 作者: <a href="http://www.cnblogs.com/glacierh/" target="_blank">Glacier</a> 发表于 2009-07-19 21:05 <a href="http://www.cnblogs.com/glacierh/archive/2009/07/19/1526670.html" target="_blank">原文链接</a></p>&nbsp; 
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">多态是面向对象的三个基本特性之一，因此在</span><span lang="EN-US">C#</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中正确理解和实现多态是非常重要的。</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对于</span><span lang="EN-US">C#</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">初学者而言，可能已经理解了多态的概念，但对于多态的实现，特别是关键字</span><span lang="EN-US">new</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</span><span lang="EN-US">virtual</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</span><span lang="EN-US">override</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的使用，仍然有种一头雾水的感觉。我查阅几本书，在网上看了一些相关的资料，总算是小有收获，在这里分享一下我的理解，希望对初学者有所帮助。</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">多态可以简单的理解为对不同的对象调用相同的方法，表现出不同的行为，这种特性是通过继承来实现的。先来看一个简单的例子，展现一下多态的实现。</span></p>
<p class="MsoNormal"><strong style="mso-bidi-font-weight: normal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">例</span><span lang="EN-US">1</span></strong><strong style="mso-bidi-font-weight: normal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</span><span lang="EN-US"><o:p></o:p></span></strong></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"></p>
<div class="cnblogs_code"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Animal<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">virtual</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Eat()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="color: #800000">"</span><span style="color: #800000">Animal&nbsp;eat<img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span style="color: #800000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Cat&nbsp;:&nbsp;Animal<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">override</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Eat()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="color: #800000">"</span><span style="color: #800000">Cat&nbsp;eat<img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span style="color: #800000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Dog&nbsp;:&nbsp;Animal<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">override</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Eat()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="color: #800000">"</span><span style="color: #800000">Dog&nbsp;eat<img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span style="color: #800000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Tester<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Main(</span><span style="color: #0000ff">string</span><span style="color: #000000">[]&nbsp;args)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Animal[]&nbsp;animals&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Animal[</span><span style="color: #800080">3</span><span style="color: #000000">];<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;animals[</span><span style="color: #800080">0</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Animal();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;animals[</span><span style="color: #800080">1</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Cat();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;animals[</span><span style="color: #800080">2</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Dog();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #800080">0</span><span style="color: #000000">;&nbsp;i&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #800080">3</span><span style="color: #000000">;&nbsp;i</span><span style="color: #000000">++</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;animals[i].Eat();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span></div>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><br />&nbsp;&nbsp;&nbsp;&nbsp;输出如下：</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span lang="EN-US">Animal eat...</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span lang="EN-US">Cat eat...</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span lang="EN-US">Dog eat...</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在上面的例子中，通过继承，使得</span><span lang="EN-US">Animal</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象数组中的不同的对象，在调用</span><span lang="EN-US">Eat()</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法时，表现出了不同的行为。</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">多态的实现看起来很简单，要完全理解及灵活的运用</span><span lang="EN-US">c#</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的多态机制，也不是一件容易的事，有很多需要注意的地方。</span></p>
<p class="MsoNormal"><strong style="mso-bidi-font-weight: normal"><span style="font-size: 14pt" lang="EN-US">1. new</span></strong><strong style="mso-bidi-font-weight: normal"><span style="font-family: 宋体; font-size: 14pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的用法</span></strong><strong style="mso-bidi-font-weight: normal"><span style="font-size: 14pt" lang="EN-US"><o:p></o:p></span></strong></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">先看下面的例子。</span></p>
<p class="MsoNormal"><strong style="mso-bidi-font-weight: normal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">例</span><span lang="EN-US">2</span></strong><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></p>
<div class="cnblogs_code"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Animal<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">virtual</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Eat()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="color: #800000">"</span><span style="color: #800000">Animal&nbsp;eat<img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span style="color: #800000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Cat&nbsp;:&nbsp;Animal<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Eat()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="color: #800000">"</span><span style="color: #800000">Cat&nbsp;eat<img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span style="color: #800000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Tester<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Main(</span><span style="color: #0000ff">string</span><span style="color: #000000">[]&nbsp;args)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Animal&nbsp;a&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Animal();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a.Eat();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Animal&nbsp;ac&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Cat();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ac.Eat();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cat&nbsp;c&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Cat();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c.Eat();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span></div>
<p style="text-align: left; mso-layout-grid-align: none" class="MsoNormal" align="left"><br />&nbsp;&nbsp;&nbsp;&nbsp;运行结果为：</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span lang="EN-US">Animal eat...</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span lang="EN-US">Animal eat...</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span lang="EN-US">Cat eat...</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以看出，当派生类</span><span lang="EN-US">Cat</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span><span lang="EN-US">Eat()</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法使用</span><span lang="EN-US">new</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修饰时，</span><span lang="EN-US">Cat</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的对象转换为</span><span lang="EN-US">Animal</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象后，调用的是</span><span lang="EN-US">Animal</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类中的</span><span lang="EN-US">Eat()</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法。其实可以理解为，使用</span><span lang="EN-US">new</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关键字后，使得</span><span lang="EN-US">Cat</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的</span><span lang="EN-US">Eat()</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法和</span><span lang="EN-US">Animal</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的</span><span lang="EN-US">Eat()</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法成为毫不相关的两个方法，只是它们的名字碰巧相同而已。所以，</span> <span lang="EN-US">Animal</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类中的</span><span lang="EN-US">Eat()</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法不管用还是不用</span><span lang="EN-US">virtual</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修饰，也不管访问权限如何，或者是没有，都不会对</span><span lang="EN-US">Cat</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span><span lang="EN-US">Eat()</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法产生什么影响（只是因为使用了</span><span lang="EN-US">new</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关键字，如果</span><span lang="EN-US">Cat</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类没用从</span><span lang="EN-US">Animal</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类继承</span><span lang="EN-US">Eat()</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法，编译器会输出警告）。</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">我想这是设计者有意这么设计的，因为有时候我们就是要达到这种效果。严格的说，不能说通过使用</span><span lang="EN-US">new</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来实现多态，只能说在某些特定的时候碰巧实现了多态的效果。</span></p>
<p class="MsoNormal"><strong style="mso-bidi-font-weight: normal"><span style="font-size: 14pt" lang="EN-US">2.override</span></strong><strong style="mso-bidi-font-weight: normal"><span style="font-family: 宋体; font-size: 14pt; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">实现多态</span></strong><strong style="mso-bidi-font-weight: normal"><span style="font-size: 14pt" lang="EN-US"><o:p></o:p></span></strong></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">真正的多态使用</span><span lang="EN-US">override</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">来实现的。回过去看前面的例</span><span lang="EN-US">1</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，在基类</span><span lang="EN-US">Animal</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中将方法</span><span lang="EN-US">Eat()</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">用</span><span lang="EN-US">virtual</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">标记为虚拟方法，再在派生类</span><span lang="EN-US">Cat</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span><span lang="EN-US">Dog</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中用</span><span lang="EN-US">override</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对</span><span lang="EN-US">Eat()</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修饰，进行重写，很简单就实现了多态。需要注意的是，要对一个类中一个方法用</span><span lang="EN-US">override</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修饰，该类必须从父类中继承了一个对应的用</span><span lang="EN-US">virtual</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修饰的虚拟方法，否则编译器将报错。</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">好像讲得差不多了，还有一个问题，不知道你想没有。就是多层继承中又是怎样实现多态的。比如类</span><span lang="EN-US">A</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是基类，有一个虚拟方法</span><span lang="EN-US">method()</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（</span><span lang="EN-US">virtual</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修饰），类</span><span lang="EN-US">B</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">继承自类</span><span lang="EN-US">A</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，并对</span><span lang="EN-US">method()</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">进行重写（</span><span lang="EN-US">override</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修饰），现在类</span><span lang="EN-US">C</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">又继承自类</span><span lang="EN-US">B</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，是不是可以继续对</span><span lang="EN-US">method()</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">进行重写，并实现多态呢？看下面的例子。</span></p>
<p class="MsoNormal"><strong style="mso-bidi-font-weight: normal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">例</span><span lang="EN-US">3</span></strong><strong style="mso-bidi-font-weight: normal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：<br /></span></strong><span style="font-family: 新宋体; font-size: 9pt; mso-hansi-font-family: 'Times New Roman'; mso-font-kerning: 0pt; mso-no-proof: yes" lang="EN-US"><span style="mso-spacerun: yes"><br /></p>
<div class="cnblogs_code"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Animal<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">virtual</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Eat()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="color: #800000">"</span><span style="color: #800000">Animal&nbsp;eat</span><span style="color: #800000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Dog&nbsp;:&nbsp;Animal<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">override</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Eat()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="color: #800000">"</span><span style="color: #800000">Dog&nbsp;eat</span><span style="color: #800000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;WolfDog&nbsp;:&nbsp;Dog<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">override</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Eat()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="color: #800000">"</span><span style="color: #800000">WolfDog&nbsp;eat</span><span style="color: #800000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Tester<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Main(</span><span style="color: #0000ff">string</span><span style="color: #000000">[]&nbsp;args)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Animal[]&nbsp;animals&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Animal[</span><span style="color: #800080">3</span><span style="color: #000000">];<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;animals[</span><span style="color: #800080">0</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Animal();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;animals[</span><span style="color: #800080">1</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Dog();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;animals[</span><span style="color: #800080">2</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;WolfDog();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #800080">0</span><span style="color: #000000">;&nbsp;i&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #800080">3</span><span style="color: #000000">;&nbsp;i</span><span style="color: #000000">++</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;animals[i].Eat();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span></div>
<p class="MsoNormal"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">运行结果为：</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span lang="EN-US">Animal eat...</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span lang="EN-US">Dog eat...</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span lang="EN-US">WolfDog eat...</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&nbsp;<br /><br /></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在上面的例子中类</span><span lang="EN-US">Dog</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">继承自类</span><span lang="EN-US">Animal</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，对方法</span><span lang="EN-US">Eat()</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">进行了重写，类</span><span lang="EN-US">WolfDog</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">又继承自</span><span lang="EN-US">Dog</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，再一次对</span><span lang="EN-US">Eat()</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法进行了重写，并很好地实现了多态。不管继承了多少层，都可以在子类中对父类中已经重写的方法继续进行重写，即如果父类方法用</span><span lang="EN-US">override</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修饰，如果子类继承了该方法，也可以用</span><span lang="EN-US">override</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修饰，多层继承中的多态就是这样实现的。要想终止这种重写，只需重写方法时用</span><span lang="EN-US">sealed</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关键字进行修饰即可。&nbsp; </p>
<p><strong><span style="font-size: 14pt">3. abstract-override</span></strong><strong><span style="font-family: 宋体; font-size: 14pt">实现多态</span></strong><strong><span style="font-size: 14pt"></span></strong></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">先在我们在来讨论一下用</span>abstract<span style="font-family: 宋体">修饰的抽象方法。抽象方法只是对方法进行了定义，而没有实现，如果一个类包含了抽象方法，那么该类也必须用</span>abstract<span style="font-family: 宋体">声明为抽象类，一个抽象类是不能被实例化的。对于类中的抽象方法，可以再其派生类中用</span>override<span style="font-family: 宋体">进行重写，如果不重写，其派生类也要被声明为抽象类。看下面的例子。</span></p>
<p><strong><span style="font-family: 宋体">例</span>4</strong><strong><span style="font-family: 宋体">：<br /><br /></span></strong></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"></span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"></p>
<div class="cnblogs_code"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">abstract</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Animal<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Cat&nbsp;:&nbsp;Animal<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">override</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Eat()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="color: #800000">"</span><span style="color: #800000">Cat&nbsp;eat<img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span style="color: #800000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Dog&nbsp;:&nbsp;Animal<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">override</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Eat()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="color: #800000">"</span><span style="color: #800000">Dog&nbsp;eat<img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span style="color: #800000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;WolfDog&nbsp;:&nbsp;Dog<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">override</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Eat()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="color: #800000">"</span><span style="color: #800000">Wolfdog&nbsp;eat<img alt="" src="http://www.cnblogs.com/Images/dot.gif" /></span><span style="color: #800000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Tester<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Main(</span><span style="color: #0000ff">string</span><span style="color: #000000">[]&nbsp;args)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Animal[]&nbsp;animals&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Animal[</span><span style="color: #800080">3</span><span style="color: #000000">];<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;animals[</span><span style="color: #800080">0</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Cat();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;animals[</span><span style="color: #800080">1</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Dog();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;animals[</span><span style="color: #800080">2</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;WolfDog();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #800080">0</span><span style="color: #000000">;&nbsp;i&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;animals.Length;&nbsp;i</span><span style="color: #000000">++</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;animals[i].Eat();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span></div>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span style="font-family: 新宋体; font-size: 9pt"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;运行结果为：</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span lang="EN-US">Cat eat...</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span lang="EN-US">Dog eat...</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span lang="EN-US">Wolfdog eat...</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">从上面可以看出，通过使用</span><span lang="EN-US">abstract-override</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以和</span><span lang="EN-US">virtual-override</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一样地实现多态，包括多层继承也是一样的。不同之处在于，包含虚拟方法的类可以被实例化，而包含抽象方法的类不能被实例化。</span></p>
<p style="text-indent: 21pt; mso-char-indent-count: 2.0" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以上就是我对</span><span lang="EN-US">c#</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中多态的一些浅薄的认识，如有错误的地方，欢迎批评指正！</span></span></p></span></span> <img src="http://www.cnblogs.com/glacierh/aggbug/1526670.html?type=1" width="1" height="1" alt=""/><p>评论: 1　<a href="http://www.cnblogs.com/glacierh/archive/2009/07/19/1526670.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/glacierh/archive/2009/07/19/1526670.html#commentform" target="_blank">发表评论</a></p><p><a href="http://job.cnblogs.com/" target="_blank">找优秀程序员，就在博客园</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/59187/" target="_blank">Notifo推iPhone应用：弥补邮件推送缺陷</a><span style="color:gray">(2010-03-19 21:04)</span><br/>· <a href="http://news.cnblogs.com/n/59186/" target="_blank">分析：微软IE9现身 网络视频标准争议依旧未解</a><span style="color:gray">(2010-03-19 20:57)</span><br/>· <a href="http://news.cnblogs.com/n/59185/" target="_blank">连线朱骏：陈晓薇离开九城与魔兽无关</a><span style="color:gray">(2010-03-19 20:52)</span><br/>· <a href="http://news.cnblogs.com/n/59184/" target="_blank">九城总裁陈晓薇5月期满离任 朱骏将代理总裁</a><span style="color:gray">(2010-03-19 20:48)</span><br/>· <a href="http://news.cnblogs.com/n/59183/" target="_blank">Google携手Intel和Sony推出&quot;Google电视&quot;</a><span style="color:gray">(2010-03-19 20:44)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/59093/" target="_blank">[视频]想做你的Code</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>C# 委托的妙文(转)</title><link>http://www.cnblogs.com/glacierh/archive/2009/07/11/1521476.html</link><dc:creator>Glacier</dc:creator><author>Glacier</author><pubDate>Sat, 11 Jul 2009 09:28:00 GMT</pubDate><guid>http://www.cnblogs.com/glacierh/archive/2009/07/11/1521476.html</guid><description><![CDATA[<p>阅读: 158 评论: 1 作者: <a href="http://www.cnblogs.com/glacierh/" target="_blank">Glacier</a> 发表于 2009-07-11 17:28 <a href="http://www.cnblogs.com/glacierh/archive/2009/07/11/1521476.html" target="_blank">原文链接</a></p><p>委托和事件在 .Net Framework中的应用非常广泛，然而，较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。它们就像是一道槛儿，过了这个槛的人，觉得真是太容易了，而没有过去的人每次见到委托和事件就觉得心里别（bi&#232;）得慌，混身不自在。本文中，我将通过两个范例由浅入深地讲述什么是委托、为什么要使用委托、事件的由来、.Net Framework中的委托和事件、委托和事件对Observer设计模式的意义，对它们的中间代码也做了讨论。 </p>
<p>将方法作为方法的参数<br />我们先不管这个标题如何的绕口，也不管委托究竟是个什么东西，来看下面这两个最简单的方法，它们不过是在屏幕上输出一句问候的话语： </p>
<p>以下为引用的内容：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void GreetPeople(string name) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 做某些额外的事情，比如初始化之类，此处略<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EnglishGreeting(name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void EnglishGreeting(string name) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;Morning, &#8221; + name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;</p>
<p>暂且不管这两个方法有没有什么实际意义。GreetPeople用于向某人问好，当我们传递代表某人姓名的name参数，比如说&#8220;Jimmy&#8221;，进去的时候，在这个方法中，将调用EnglishGreeting方法，再次传递name参数，EnglishGreeting则用于向屏幕输出 &#8220;Morning, Jimmy&#8221;。 </p>
<p>现在假设这个程序需要进行全球化，哎呀，不好了，我是人，我不明白&#8220;Morning&#8221;是什么意思，怎么办呢？好吧，我们再加个中文版的问候方法：</p>
<p>以下为引用的内容：<br />public void ChineseGreeting(string name){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;早上好, &#8221; + name);<br />}<br />&nbsp;</p>
<p>这时候，GreetPeople也需要改一改了，不然如何判断到底用哪个版本的Greeting问候方法合适呢？在进行这个之前，我们最好再定义一个枚举作为判断的依据： <br />以下为引用的内容：<br />public enum Language{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; English, Chinese<br />}<br />public void GreetPeople(string name, Language lang){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //做某些额外的事情，比如初始化之类，此处略<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; swith(lang){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case Language.English:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EnglishGreeting(name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case Language.Chinese:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ChineseGreeting(name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />}<br />&nbsp; <br />OK，尽管这样解决了问题，但我不说大家也很容易想到，这个解决方案的可扩展性很差，如果日后我们需要再添加韩文版、日文版，就不得不反复修改枚举和GreetPeople()方法，以适应新的需求。</p>
<p>在考虑新的解决方案之前，我们先看看 GreetPeople的方法签名：<br />public void GreetPeople(string name, Language lang) </p>
<p>我们仅看 string name，在这里，string 是参数类型，name 是参数变量，当我们赋给name字符串&#8220;jimmy&#8221;时，它就代表&#8220;jimmy&#8221;这个值；当我们赋给它&#8220;张子阳&#8221;时，它又代表着&#8220;张子阳&#8221;这个值。然后，我们可以在方法体内对这个name进行其他操作。哎，这简直是废话么，刚学程序就知道了。 Www~</p>
<p>如果你再仔细想想，假如GreetPeople()方法可以接受一个参数变量，这个变量可以代表另一个方法，当我们给这个变量赋值 EnglishGreeting的时候，它代表着 EnglsihGreeting() 这个方法；当我们给它赋值ChineseGreeting 的时候，它又代表着ChineseGreeting()方法。我们将这个参数变量命名为 MakeGreeting，那么不是可以如同给name赋值时一样，在调用 GreetPeople()方法的时候，给这个MakeGreeting 参数也赋上值么(ChineseGreeting或者EnglsihGreeting等)？然后，我们在方法体内，也可以像使用别的参数一样使用MakeGreeting。但是，由于MakeGreeting代表着一个方法，它的使用方式应该和它被赋的方法(比如ChineseGreeting)是一样的，比如： </p>
<p>MakeGreeting(name);</p>
<p>好了，有了思路了，我们现在就来改改GreetPeople()方法，那么它应该是这个样子了：<br />以下为引用的内容：<br />public void GreetPeople(string name, *** MakeGreeting){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MakeGreeting(name);<br />}</p>
<p>注意到 *** ，这个位置通常放置的应该是参数的类型，但到目前为止，我们仅仅是想到应该有个可以代表方法的参数，并按这个思路去改写GreetPeople方法，现在就出现了一个大问题：这个代表着方法的MakeGreeting参数应该是什么类型的？ </p>
<p>NOTE：这里已不再需要枚举了，因为在给MakeGreeting赋值的时候动态地决定使用哪个方法，是ChineseGreeting还是 EnglishGreeting，而在这个两个方法内部，已经对使用&#8220;morning&#8221;还是&#8220;早上好&#8221;作了区分。 </p>
<p>聪明的你应该已经想到了，现在是委托该出场的时候了，但讲述委托之前，我们再看看MakeGreeting参数所能代表的 ChineseGreeting()和EnglishGreeting()方法的签名：<br />public void EnglishGreeting(string name)<br />public void ChineseGreeting(string name)</p>
<p>如同name可以接受String类型的&#8220;true&#8221;和&#8220;1&#8221;，但不能接受bool类型的true和int类型的1一样。MakeGreeting的 参数类型定义 应该能够确定 MakeGreeting可以代表的 方法种类，再进一步讲，就是MakeGreeting可以代表的方法 的 参数类型和祷乩嘈汀?br /&gt; 于是，委托出现了：它定义了MakeGreeting参数所能代表的方法的种类，也就是MakeGreeting参数的类型。<br />NOTE：如果上面这句话比较绕口，我把它翻译成这样：string 定义了name参数所能代表的值的种类，也就是name参数的类型。 </p>
<p>本例中委托的定义：</p>
<p>public delegate void GreetingDelegate(string name);<br />可以与上面EnglishGreeting()方法的签名对比一下，除了加入了delegate关键字以外，其余的是不是完全一样？ </p>
<p>现在，让我们再次改动GreetPeople()方法，如下所示：</p>
<p>以下为引用的内容：<br />public void GreetPeople(string name, GreetingDelegate MakeGreeting){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MakeGreeting(name);<br />}<br />&nbsp;</p>
<p>如你所见，委托GreetingDelegate出现的位置与 string相同，string是一个类型，那么GreetingDelegate应该也是一个类型，或者叫类(Class)。但是委托的声明方式和类却完全不同，这是怎么一回事？实际上，委托在编译的时候确实会编译成类。因为Delegate是一个类，所以在任何可以声明类的地方都可以声明委托。更多的内容将在下面讲述，现在，请看看这个范例的完整代码：</p>
<p>.</p>
<p>以下为引用的内容：<br />using System;<br />using System.Collections.Generic;<br />using System.Text;<br />namespace Delegate {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //定义委托，它定义了可以代表的方法的类型<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public delegate void GreetingDelegate(string name);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Program {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static void EnglishGreeting(string name) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;Morning, &#8221; + name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } Www~</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static void ChineseGreeting(string name) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;早上好, &#8221; + name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注意此方法，它接受一个GreetingDelegate类型的方法作为参数<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static void GreetPeople(string name, GreetingDelegate MakeGreeting) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MakeGreeting(name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetPeople(&#8221;Jimmy Zhang&#8221;, EnglishGreeting);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetPeople(&#8221;张子阳&#8221;, ChineseGreeting);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.ReadKey();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />} Www~<br />&nbsp;</p>
<p>输出如下：</p>
<p>Morning, Jimmy Zhang </p>
<p>早上好, 张子阳</p>
<p>我们现在对委托做一个总结： </p>
<p>委托是一个类，它定义了方法的类型，使得可以将方法当作另一个方法的参数来进行传递，这种将方法动态地赋给参数的做法，可以避免在程序中大量使用If-Else(Switch)语句，同时使得程序具有更好的可扩展性。 </p>
<p>将方法绑定到委托 .</p>
<p>看到这里，是不是有那么点如梦初醒的感觉？于是，你是不是在想：在上面的例子中，我不一定要直接在GreetPeople()方法中给 name参数赋值，我可以像这样使用变量： </p>
<p>以下为引用的内容：<br />static void Main(string[] args) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string name1, name2;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name1 = &#8220;Jimmy Zhang&#8221;;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name2 = &#8220;张子阳&#8221;;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetPeople(name1, EnglishGreeting);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetPeople(name2, ChineseGreeting);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.ReadKey();<br />}<br />&nbsp;<br />而既然委托GreetingDelegate 和 类型 string 的地位一样，都是定义了一种参数类型，那么，我是不是也可以这么使用委托？<br />以下为引用的内容：<br />static void Main(string[] args) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetingDelegate delegate1, delegate2;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delegate1 = EnglishGreeting;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delegate2 = ChineseGreeting;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetPeople(&#8221;Jimmy Zhang&#8221;, delegate1);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetPeople(&#8221;张子阳&#8221;, delegate2);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.ReadKey();<br />}<br />如你所料，这样是没有问题的，程序一如预料的那样输出。这里，我想说的是委托不同于string的一个特性：可以将多个方法赋给同一个委托，或者叫将多个方法绑定到同一个委托，当调用这个委托的时候，将依次调用其所绑定的方法。在这个例子中，语法如下： </p>
<p>以下为引用的内容：<br />static void Main(string[] args) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetingDelegate delegate1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delegate1 = EnglishGreeting;&nbsp;&nbsp;&nbsp;&nbsp; // 先给委托类型的变量赋值<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delegate1 += ChineseGreeting;&nbsp;&nbsp;&nbsp;&nbsp; // 给此委托变量再绑定一个方法 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将先后调用 EnglishGreeting 与 ChineseGreeting 方法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetPeople(&#8221;Jimmy Zhang&#8221;, delegate1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.ReadKey();<br />}</p>
<p>输出为：<br />Morning, Jimmy Zhang </p>
<p>早上好, Jimmy Zhang</p>
<p>实际上，我们可以也可以绕过GreetPeople方法，通过委托来直接调用EnglishGreeting和ChineseGreeting：</p>
<p>以下为引用的内容：<br />static void Main(string[] args) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetingDelegate delegate1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delegate1 = EnglishGreeting;&nbsp;&nbsp;&nbsp;&nbsp; // 先给委托类型的变量赋值<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delegate1 += ChineseGreeting;&nbsp;&nbsp;&nbsp;&nbsp; // 给此委托变量再绑定一个方法 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将先后调用 EnglishGreeting 与 ChineseGreeting 方法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delegate1 (&#8221;Jimmy Zhang&#8221;);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.ReadKey();<br />}<br />&nbsp;<br />NOTE：这在本例中是没有问题的，但回头看下上面GreetPeople()的定义，在它之中可以做一些对于EnglshihGreeting和ChineseGreeting来说都需要进行的工作，为了简便我做了省略。</p>
<p>Www~<br />注意这里，第一次用的&#8220;=&#8221;，是赋值的语法；第二次，用的是&#8220;+=&#8221;，是绑定的语法。如果第一次就使用&#8220;+=&#8221;，将出现&#8220;使用了未赋值的局部变量&#8221;的编译错误。<br />我们也可以使用下面的代码来这样简化这一过程： </p>
<p>GreetingDelegate delegate1 = new GreetingDelegate(EnglishGreeting);</p>
<p>delegate1 += ChineseGreeting;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 给此委托变量再绑定一个方法 @com</p>
<p>看到这里，应该注意到，这段代码第一条语句与实例化一个类是何其的相似，你不禁想到：上面第一次绑定委托时不可以使用&#8220;+=&#8221;的编译错误，或许可以用这样的方法来避免：</p>
<p>GreetingDelegate delegate1 = new GreetingDelegate(); </p>
<p>delegate1 += EnglishGreeting;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 这次用的是 &#8220;+=&#8221;，绑定语法。</p>
<p>.</p>
<p>delegate1 += ChineseGreeting;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 给此委托变量再绑定一个方法 </p>
<p>但实际上，这样会出现编译错误： &#8220;GreetingDelegate&#8221;方法没有采用&#8220;0&#8221;个参数的重载。尽管这样的结果让我们觉得有点沮丧，但是编译的提示：&#8220;没有0个参数的重载&#8221;再次让我们联想到了类的构造函数。我知道你一定按捺不住想探个究竟，但再此之前，我们需要先把基础知识和应用介绍完。 </p>
<p>既然给委托可以绑定一个方法，那么也应该有办法取消对方法的绑定，很容易想到，这个语法是&#8220;-=&#8221;：</p>
<p>以下为引用的内容：<br />static void Main(string[] args) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetingDelegate delegate1 = new GreetingDelegate(EnglishGreeting);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delegate1 += ChineseGreeting;&nbsp;&nbsp;&nbsp; // 给此委托变量再绑定一个方法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将先后调用 EnglishGreeting 与 ChineseGreeting 方法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetPeople(&#8221;Jimmy Zhang&#8221;, delegate1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(); </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delegate1 -= EnglishGreeting; //取消对EnglishGreeting方法的绑定<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将仅调用 ChineseGreeting<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetPeople(&#8221;张子阳&#8221;, delegate1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.ReadKey();<br />}<br />&nbsp;<br />输出为：</p>
<p>Morning, Jimmy Zhang </p>
<p>早上好, Jimmy Zhang Www_</p>
<p>早上好, 张子阳 </p>
<p>让我们再次对委托作个总结： </p>
<p>使用委托可以将多个方法绑定到同一个委托变量，当调用此变量时(这里用&#8220;调用&#8221;这个词，是因为此变量代表一个方法)，可以依次调用所有绑定的方法。 </p>
<p>事件的由来 </p>
<p>我们继续思考上面的程序：上面的三个方法都定义在Programe类中，这样做是为了理解的方便，实际应用中，通常都是 GreetPeople 在一个类中，ChineseGreeting和 EnglishGreeting 在另外的类中。现在你已经对委托有了初步了解，是时候对上面的例子做个改进了。假设我们将GreetingPeople()放在一个叫GreetingManager的类中，那么新程序应该是这个样子的：</p>
<p>Www_</p>
<p>以下为引用的内容：<br />namespace Delegate {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //定义委托，它定义了可以代表的方法的类型<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public delegate void GreetingDelegate(string name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //新建的GreetingManager类<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public class GreetingManager{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void GreetPeople(string name, GreetingDelegate MakeGreeting) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MakeGreeting(name); .<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Program {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static void EnglishGreeting(string name) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;Morning, &#8221; + name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static void ChineseGreeting(string name) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;早上好, &#8221; + name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } @com</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // &#8230; &#8230;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />}</p>
<p>Www~<br />&nbsp;<br />&nbsp;</p>
<p>这个时候，如果要实现前面演示的输出效果，Main方法我想应该是这样的：</p>
<p>以下为引用的内容：<br />static void Main(string[] args) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetingManager gm = new&nbsp; GreetingManager();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gm.GreetPeople(&#8221;Jimmy Zhang&#8221;, EnglishGreeting);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gm.GreetPeople(&#8221;张子阳&#8221;, ChineseGreeting);<br />}<br />&nbsp;</p>
<p>我们运行这段代码，嗯，没有任何问题。程序一如预料地那样输出了：<br />Morning, Jimmy Zhang<br />早上好, 张子阳</p>
<p>现在，假设我们需要使用上一节学到的知识，将多个方法绑定到同一个委托变量，该如何做呢？让我们再次改写代码： </p>
<p>以下为引用的内容：</p>
<p>static void Main(string[] args) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetingManager gm = new&nbsp; GreetingManager();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetingDelegate delegate1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delegate1 = EnglishGreeting;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delegate1 += ChineseGreeting; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gm.GreetPeople(&#8221;Jimmy Zhang&#8221;, delegate1);<br />}<br />&nbsp;<br />输出：</p>
<p>Www~<br />Morning, Jimmy Zhang</p>
<p>早上好, Jimmy Zhang<br />到了这里，我们不禁想到：面向对象设计，讲究的是对象的封装，既然可以声明委托类型的变量(在上例中是delegate1)，我们何不将这个变量封装到 GreetManager类中？在这个类的客户端中使用不是更方便么？于是，我们改写GreetManager类，像这样：</p>
<p>以下为引用的内容：<br />public class GreetingManager{<br />//在GreetingManager类的内部声明delegate1变量<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public GreetingDelegate delegate1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />public void GreetPeople(string name, GreetingDelegate MakeGreeting) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MakeGreeting(name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />}<br />&nbsp;<br />&nbsp;</p>
<p>现在，我们可以这样使用这个委托变量： <br />以下为引用的内容：<br />static void Main(string[] args) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetingManager gm = new&nbsp; GreetingManager();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gm.delegate1 = EnglishGreeting;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gm.delegate1 += ChineseGreeting;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gm.GreetPeople(&#8221;Jimmy Zhang&#8221;, gm.delegate1);<br />} <br />&nbsp;<br />尽管这样达到了我们要的效果，但是似乎并不美气，光是第一个方法注册用&#8220;=&#8221;，第二个用&#8220;+=&#8221;就让人觉得别扭。此时，轮到Event出场了，C# 中可以使用事件来专门完成这项工作，我们改写GreetingManager类，它变成了这个样子： <br />以下为引用的内容：<br />public class GreetingManager{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //这一次我们在这里声明一个事件<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public event GreetingDelegate MakeGreet;<br />public void GreetPeople(string name, GreetingDelegate MakeGreeting) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MakeGreeting(name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />} <br />&nbsp;<br />.</p>
<p>很容易注意到：MakeGreet 事件的声明与之前委托变量delegate1的声明唯一的区别是多了一个event关键字。看到这里，你差不多明白到：事件其实没什么不好理解的，声明一个事件不过类似于声明一个委托类型的变量而已。 </p>
<p>我们想当然地改写Main方法： <br />以下为引用的内容：<br />static void Main(string[] args) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GreetingManager gm = new&nbsp; GreetingManager();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gm.MakeGreet = EnglishGreeting; // 编译错误1<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gm.MakeGreet += ChineseGreeting;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gm.GreetPeople(&#8221;Jimmy Zhang&#8221;, gm.MakeGreet); //编译错误2<br />}<br />&nbsp;<br />这次，你会得到编译错误：事件&#8220;Delegate.GreetingManager.MakeGreet&#8221;只能出现在 += 或 -= 的左边(从类型&#8220;Delegate.GreetingManager&#8221;中使用时除外)。 </p>
<p>事件和委托的编译代码</p>
<p>这时候，我们不得不注释掉编译错误的行，然后重新进行编译，再借助Reflactor来对 event的声明语句做一探究，看看为什么会发生这样的错误：<br />public event GreetingDelegate MakeGreet; <br />可以看到，实际上尽管我们在GreetingManager里将 MakeGreet 声明为public，但是，实际上MakeGreet会被编译成 私有字段，难怪会发生上面的编译错误了，因为它根本就不允许在GreetingManager类的外面以赋值的方式访问。<br />我们进一步看下MakeGreet所产生的代码： </p>
<p>以下为引用的内容：</p>
<p>private GreetingDelegate MakeGreet;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //对事件的声明 实际是 声明一个私有的委托变量</p>
<p>[MethodImpl(MethodImplOptions.Synchronized)]<br />public void add_MakeGreet(GreetingDelegate value){<br />&nbsp;&nbsp;&nbsp; this.MakeGreet = (GreetingDelegate) Delegate.Combine(this.MakeGreet, value);<br />} </p>
<p>[MethodImpl(MethodImplOptions.Synchronized)]<br />public void remove_MakeGreet(GreetingDelegate value){<br />&nbsp;&nbsp;&nbsp; this.MakeGreet = (GreetingDelegate) Delegate.Remove(this.MakeGreet, value);<br />} <br />&nbsp;<br />&nbsp;</p>
<p>现在已经很明确了：MakeGreet 事件确实是一个GreetingDelegate类型的委托，只不过不管是不是声明为public，它总是被声明为private。另外，它还有两个方法，分别是add_MakeGreet和remove_MakeGreet，这两个方法分别用于注册委托类型的方法和取消注册，实际上也就是： &#8220;+= &#8221;对应 add_MakeGreet，&#8220;-=&#8221;对应remove_MakeGreet。而这两个方法的访问限制取决于声明事件时的访问限制符。 </p>
<p>在add_MakeGreet()方法内部，实际上调用了System.Delegate的Combine()静态方法，这个方法用于将当前的变量添加到委托链表中。我们前面提到过两次，说委托实际上是一个类，在我们定义委托的时候：<br />public delegate void GreetingDelegate(string name); </p>
<p>当编译器遇到这段代码的时候，会生成下面这样一个完整的类：</p>
<p>以下为引用的内容：</p>
<p>public class GreetingDelegate:System.MulticastDelegate{</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public GreetingDelegate(object @object, IntPtr method);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public virtual IAsyncResult BeginInvoke(string name, AsyncCallback callback, object @object);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public virtual void EndInvoke(IAsyncResult result);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public virtual void Invoke(string name);<br />}<br />&nbsp;<br />&nbsp;</p>
<p>关于这个类的更深入内容，可以参阅《CLR Via C#》等相关书籍，这里就不再讨论了。</p>
<p>委托、事件与Observer设计模式<br />范例说明<br />上面的例子已不足以再进行下面的讲解了，我们来看一个新的范例，因为之前已经介绍了很多的内容，所以本节的进度会稍微快一些：<br />假设我们有个高档的热水器，我们给它通上电，当水温超过95度的时候：1、扬声器会开始发出语音，告诉你水的温度；2、液晶屏也会改变水温的显示，来提示水已经快烧开了。</p>
<p>现在我们需要写个程序来模拟这个烧水的过程，我们将定义一个类来代表热水器，我们管它叫：Heater，它有代表水温的字段，叫做temperature；当然，还有必不可少的给水加热方法BoilWater()，一个发出语音警报的方法MakeAlert()，一个显示水温的方法，ShowMsg()。<br />以下为引用的内容：<br />namespace Delegate {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Heater {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int temperature; // 水温<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 烧水<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void BoilWater() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt;= 100; i++) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temperature = i;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (temperature &gt; 95) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MakeAlert(temperature);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ShowMsg(temperature);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 发出语音警报<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void MakeAlert(int param) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;Alarm：嘀嘀嘀，水已经 {0} 度了：&#8221; , param);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 显示水温<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void ShowMsg(int param) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;Display：水快开了，当前温度：{0}度。&#8221; , param);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Program {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Heater ht = new Heater();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ht.BoilWater();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />} <br />&nbsp;</p>
<p>Observer设计模式简介</p>
<p>上面的例子显然能完成我们之前描述的工作，但是却并不够好。现在假设热水器由三部分组成：热水器、警报器、显示器，它们来自于不同厂商并进行了组装。那么，应该是热水器仅仅负责烧水，它不能发出警报也不能显示水温；在水烧开时由警报器发出警报、显示器显示提示和水温。</p>
<p>这时候，上面的例子就应该变成这个样子：</p>
<p>以下为引用的内容：</p>
<p>// 热水器<br />public class Heater {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int temperature;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 烧水<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void BoilWater() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt;= 100; i++) { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temperature = i;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 警报器<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public class Alarm{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void MakeAlert(int param) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;Alarm：嘀嘀嘀，水已经 {0} 度了：&#8221; , param);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 显示器<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public class Display{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void ShowMsg(int param) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;Display：水已烧开，当前温度：{0}度。&#8221; , param);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />} <br />&nbsp;<br />这里就出现了一个问题：如何在水烧开的时候通知报警器和显示器？在继续进行之前，我们先了解一下Observer设计模式，Observer设计模式中主要包括如下两类对象：<br />Subject：监视对象，它往往包含着其他对象所感兴趣的内容。在本范例中，热水器就是一个监视对象，它包含的其他对象所感兴趣的内容，就是temprature字段，当这个字段的值快到100时，会不断把数据发给监视它的对象。 </p>
<p>Observer：监视者，它监视Subject，当Subject中的某件事发生的时候，会告知Observer，而Observer则会采取相应的行动。在本范例中，Observer有警报器和显示器，它们采取的行动分别是发出警报和显示水温。<br />在本例中，事情发生的顺序应该是这样的：</p>
<p>警报器和显示器告诉热水器，它对它的温度比较感兴趣(注册)。</p>
<p>热水器知道后保留对警报器和显示器的引用。 </p>
<p>热水器进行烧水这一动作，当水温超过95度时，通过对警报器和显示器的引用，自动调用警报器的MakeAlert()方法、显示器的ShowMsg()方法。<br />类似这样的例子是很多的，GOF对它进行了抽象，称为Observer设计模式：Observer设计模式是为了定义对象间的一种一对多的依赖关系，以便于当一个对象的状态改变时，其他依赖于它的对象会被自动告知并更新。Observer模式是一种松耦合的设计模式。 Www~</p>
<p>实现范例的Observer设计模式 </p>
<p>我们之前已经对委托和事件介绍很多了，现在写代码应该很容易了，现在在这里直接给出代码，并在注释中加以说明。<br />以下为引用的内容：<br />using System;<br />using System.Collections.Generic;<br />using System.Text;<br />namespace Delegate {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 热水器<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public class Heater {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int temperature;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public delegate void BoilHandler(int param);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //声明委托<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public event BoilHandler BoilEvent;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //声明事件 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 烧水<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void BoilWater() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt;= 100; i++) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temperature = i;</p>
<p>Www~<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (temperature &gt; 95) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (BoilEvent != null) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //如果有对象注册<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BoilEvent(temperature);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //调用所有注册对象的方法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 警报器<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public class Alarm {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void MakeAlert(int param) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;Alarm：嘀嘀嘀，水已经 {0} 度了：&#8221;, param);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 显示器<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public class Display {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void ShowMsg(int param) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //静态方法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;Display：水快烧开了，当前温度：{0}度。&#8221;, param);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Program {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Heater heater = new Heater();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Alarm alarm = new Alarm();</p>
<p>.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; heater.BoilEvent += alarm.MakeAlert;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注册方法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; heater.BoilEvent += (new Alarm()).MakeAlert;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //给匿名对象注册方法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; heater.BoilEvent += Display.ShowMsg;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注册静态方法 .</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; heater.BoilWater();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //烧水，会自动调用注册过对象的方法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />}</p>
<p>输出为： </p>
<p>Alarm：嘀嘀嘀，水已经 96 度了： Www_</p>
<p>Alarm：嘀嘀嘀，水已经 96 度了： </p>
<p>Display：水快烧开了，当前温度：96度。<br />// 省略&#8230; @com</p>
<p>.Net Framework中的委托与事件 </p>
<p>尽管上面的范例很好地完成了我们想要完成的工作，但是我们不仅疑惑：为什么.Net Framework 中的事件模型和上面的不同？为什么有很多的EventArgs参数？ </p>
<p>在回答上面的问题之前，我们先搞懂 .Net Framework的编码规范： </p>
<p>委托类型的名称都应该以EventHandler结束。<br />委托的原型定义：有一个void返回值，并接受两个输入参数：一个Object 类型，一个 EventArgs类型(或继承自EventArgs)。 </p>
<p>事件的命名为 委托去掉 EventHandler之后剩余的部分。 </p>
<p>继承自EventArgs的类型应该以EventArgs结尾。<br />再做一下说明：<br />委托声明原型中的Object类型的参数代表了Subject，也就是监视对象，在本例中是 Heater(热水器)。回调函数(比如Alarm的MakeAlert)可以通过它访问触发事件的对象(Heater)。</p>
<p>EventArgs 对象包含了Observer所感兴趣的数据，在本例中是temperature。<br />上面这些其实不仅仅是为了编码规范而已，这样也使得程序有更大的灵活性。比如说，如果我们不光想获得热水器的温度，还想在Observer端(警报器或者显示器)方法中获得它的生产日期、型号、价格，那么委托和方法的声明都会变得很麻烦，而如果我们将热水器的引用传给警报器的方法，就可以在方法中直接访问热水器了。 </p>
<p>现在我们改写之前的范例，让它符合 .Net Framework 的规范： </p>
<p>以下为引用的内容：</p>
<p>using System;<br />using System.Collections.Generic;<br />using System.Text;</p>
<p>namespace Delegate {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 热水器<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public class Heater {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int temperature;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public string type = &#8220;RealFire 001&#8243;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 添加型号作为演示<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public string area = &#8220;China Xian&#8221;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 添加产地作为演示<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //声明委托<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public delegate void BoiledEventHandler(Object sender, BoliedEventArgs e);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public event BoiledEventHandler Boiled;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //声明事件 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 定义BoliedEventArgs类，传递给Observer所感兴趣的信息<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public class BoliedEventArgs : EventArgs {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public readonly int temperature;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public BoliedEventArgs(int temperature) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.temperature = temperature;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 可以供继承自 Heater 的类重写，以便继承类拒绝其他对象对它的监视<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected virtual void OnBolied(BoliedEventArgs e) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (Boiled != null) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 如果有对象注册<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Boiled(this, e);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 调用所有注册对象的方法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 烧水。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void BoilWater() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt;= 100; i++) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temperature = i;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (temperature &gt; 95) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //建立BoliedEventArgs 对象。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BoliedEventArgs e = new BoliedEventArgs(temperature); .<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OnBolied(e);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 调用 OnBolied方法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 警报器<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public class Alarm {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void MakeAlert(Object sender, Heater.BoliedEventArgs e) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Heater heater = (Heater)sender;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //这里是不是很熟悉呢？<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //访问 sender 中的公共字段<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;Alarm：{0} - {1}: &#8220;, heater.area, heater.type);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;Alarm: 嘀嘀嘀，水已经 {0} 度了：&#8221;, e.temperature); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 显示器<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public class Display {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void ShowMsg(Object sender, Heater.BoliedEventArgs e) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //静态方法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Heater heater = (Heater)sender;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;Display：{0} - {1}: &#8220;, heater.area, heater.type);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(&#8221;Display：水快烧开了，当前温度：{0}度。&#8221;, e.temperature);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Program {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Heater heater = new Heater();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Alarm alarm = new Alarm();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; heater.Boiled += alarm.MakeAlert;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注册方法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; heater.Boiled += (new Alarm()).MakeAlert;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //给匿名对象注册方法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; heater.Boiled += new Heater.BoiledEventHandler(alarm.MakeAlert);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //也可以这么注册<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; heater.Boiled += Display.ShowMsg;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注册静态方法 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; heater.BoilWater();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //烧水，会自动调用注册过对象的方法<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />}</p>
<p>Www_<br />&nbsp;</p>
<p>输出为：</p>
<p>以下为引用的内容：<br />Alarm：China Xian - RealFire 001:<br />Alarm: 嘀嘀嘀，水已经 96 度了：<br />Alarm：China Xian - RealFire 001:<br />Alarm: 嘀嘀嘀，水已经 96 度了：<br />Alarm：China Xian - RealFire 001:<br />Alarm: 嘀嘀嘀，水已经 96 度了：<br />Display：China Xian - RealFire 001:<br />Display：水快烧开了，当前温度：96度。<br />// 省略 &#8230;<br />总结 </p>
<p>在本文中我首先通过一个GreetingPeople的小程序向大家介绍了委托的概念、委托用来做什么，随后又引出了事件，接着对委托与事件所产生的中间代码做了粗略的讲述。 </p>
<p>在第二个稍微复杂点的热水器的范例中，我向大家简要介绍了 Observer设计模式，并通过实现这个范例完成了该模式，随后讲述了.Net Framework中委托、事件的实现方式。</p>
<p><br />本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/fdsa123456/archive/2009/02/11/3877678.aspx</p> <img src="http://www.cnblogs.com/glacierh/aggbug/1521476.html?type=1" width="1" height="1" alt=""/><p>评论: 1　<a href="http://www.cnblogs.com/glacierh/archive/2009/07/11/1521476.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/glacierh/archive/2009/07/11/1521476.html#commentform" target="_blank">发表评论</a></p><p><a href="http://job.cnblogs.com/" target="_blank">找优秀程序员，就在博客园</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/59187/" target="_blank">Notifo推iPhone应用：弥补邮件推送缺陷</a><span style="color:gray">(2010-03-19 21:04)</span><br/>· <a href="http://news.cnblogs.com/n/59186/" target="_blank">分析：微软IE9现身 网络视频标准争议依旧未解</a><span style="color:gray">(2010-03-19 20:57)</span><br/>· <a href="http://news.cnblogs.com/n/59185/" target="_blank">连线朱骏：陈晓薇离开九城与魔兽无关</a><span style="color:gray">(2010-03-19 20:52)</span><br/>· <a href="http://news.cnblogs.com/n/59184/" target="_blank">九城总裁陈晓薇5月期满离任 朱骏将代理总裁</a><span style="color:gray">(2010-03-19 20:48)</span><br/>· <a href="http://news.cnblogs.com/n/59183/" target="_blank">Google携手Intel和Sony推出&quot;Google电视&quot;</a><span style="color:gray">(2010-03-19 20:44)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/59093/" target="_blank">[视频]想做你的Code</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>C#中的特性(Attributes)(翻译)(转)</title><link>http://www.cnblogs.com/glacierh/archive/2009/07/11/1521445.html</link><dc:creator>Glacier</dc:creator><author>Glacier</author><pubDate>Sat, 11 Jul 2009 08:02:00 GMT</pubDate><guid>http://www.cnblogs.com/glacierh/archive/2009/07/11/1521445.html</guid><description><![CDATA[<p>阅读: 100 评论: 0 作者: <a href="http://www.cnblogs.com/glacierh/" target="_blank">Glacier</a> 发表于 2009-07-11 16:02 <a href="http://www.cnblogs.com/glacierh/archive/2009/07/11/1521445.html" target="_blank">原文链接</a></p><p><span lang="EN-US"><a href="http://www.codeproject.com/csharp/attributes.asp"><span lang="EN-US"><span lang="EN-US">原<span lang="EN-US">文</span></span></a></span></span></p>
<p><span lang="EN-US"><span lang="EN-US">转自<a href="http://www.cnblogs.com/sifang2004/archive/2006/01/12/316313.html">http://www.cnblogs.com/sifang2004/archive/2006/01/12/316313.html</a></span></p><span style="color: #ff0000">
<p><span>约定：</span></p>
<p><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>1.&#8221;attribute&#8221;</span><span>和</span><span lang="EN-US">&#8221;attributes&#8221;</span><span>均不翻译</span></p>
<p><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>2.&#8221;property&#8221;</span><span>译为&#8220;属性&#8221;</span></p>
<p><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>3.msdn</span><span>中的原句不翻译</span></p>
<p><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>4.&#8221;program entity&#8221;</span><span>译为</span><span lang="EN-US">&#8221;</span><span>语言元素</span><span lang="EN-US">&#8221;</span></p></span>
<p align="center"><strong><span lang="EN-US">Attributes in C#</span></strong><strong></strong></p>
<p align="left"><strong><span style="color: #ff9900">介绍</span></strong><strong></strong></p>
<p align="left"><span lang="EN-US">Attributes</span><span>是一种新的描述信息，我们既可以使用</span><span lang="EN-US">attributes</span><span>来定义设计期信息（例如</span><span> </span><span>帮助文件，文档的</span><span lang="EN-US">URL</span><span>），还可以用</span><span lang="EN-US">attributes</span><span>定义运行时信息（例如，使</span><span lang="EN-US">XML</span><span>中的元素与类的成员字段关联起来）。我们也可以用</span><span lang="EN-US">attributes</span><span>来创建一个&#8220;自描述&#8221;的组件。在这篇指南中我们将明白怎么创建属性并将其绑定至各种语言元素上，另外我们怎样在运行时环境下获取到</span><span lang="EN-US">attributes</span><span>的一些信息。</span><span lang="EN-US"> </span></p>
<p align="left"><strong><span style="color: #ff9900">定义</span></strong><strong></strong></p>
<p align="left"><span lang="EN-US">MSDN </span><span>中做如下定义</span><span lang="EN-US">(ms-help://MS.MSDNQTR.2002APR.1033/csspec/html/vclrfcsharpspec_17_2.htm) </span></p>
<p align="left"><em><span lang="EN-US">"An attribute is a piece of additional declarative information that is specified for a declaration."&nbsp;</span></em><span lang="EN-US"> </span></p>
<p align="left"><strong><span style="color: #ff9900"><strong><span>使用预定义</span></strong><strong><span lang="EN-US"> Attributes</span></strong></span></strong></p>
<p align="left"><span>在</span><span lang="EN-US">c#</span><span>中已有一小组预定义的</span><span lang="EN-US">attributes</span><span>，在我们学习怎样创建自定义</span><span lang="EN-US">attributes</span><span>前，先来了解下在我们的代码中使用那些预定义的</span><span lang="EN-US">attributes.<br /></p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;System;<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;AnyClass&nbsp;<br /><br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;[Obsolete(</span><span style="color: #000000">"</span><span style="color: #000000">Don't&nbsp;use&nbsp;Old&nbsp;method,&nbsp;use&nbsp;New&nbsp;method</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">)]<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Old(&nbsp;)&nbsp;{&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;New(&nbsp;)&nbsp;{&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Main(&nbsp;)&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Old(&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span></div>
<p align="left"></span><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span>仔细看下该实例，在该实例中我们用到了</span><span lang="CS">&#8221;Obsolete&#8221;attribute</span><span>，它标记了一个不该再被使用的语言元素</span><span>（<span style="color: #008080">译者注：这里的元素为方法</span>）</span><span>，该属性的第一个参数是</span><span lang="CS">string</span><span>类型，它解释为什么该元素被荒弃，以及我们该使用什么元素来代替它。实际中，我们可以书写任何其它文本来代替这段文本。第二个参数是告诉编译器把依然使用这被标识的元素视为一种错误，这就意味着编译器会因此而产生一个警告。</span><span lang="EN-US"> </span></p>
<p align="left"><span>当我们试图编译上面的上面的程序，我们会得到如下错误：</span><span lang="EN-US"> </span></p>
<p align="left"><span style="background-color: #ffcc00" lang="EN-US">AnyClass.Old()' is obsolete: 'Don't use Old method,<span>&nbsp; </span>use New method'</span></p>
<p align="left"><strong><span style="color: #ff9900"><strong><span>开发自定义</span></strong><strong><span lang="EN-US">Attributes</span></strong></span></strong></p>
<p align="left"><span>现在我们即将了解怎么开发自定义的</span><span lang="EN-US">attributes</span><span>。这儿有个小小处方，有它我们就可以学会创建自定义的</span><span lang="EN-US">attributes</span><span>。</span><span lang="EN-US"> </span></p>
<p align="left"><span>在</span><span lang="EN-US">C#</span><span>中，我们的</span><span lang="EN-US">attribute</span><span>类都派生于</span><span lang="EN-US">System.Attribute</span><span>类</span><span lang="EN-US"> (<span style="color: #3366ff">A class that derives from the abstract class System.Attribute, whether directly or indirectly, is an attribute class. The declaration of an attribute class defines a new kind of attribute that can be placed on a declaration</span>) </span><span>，我们就这么行动吧。</span><span lang="EN-US"> </span></p>
<p align="left">
<p align="left"><span lang="CS"></span></p><span>
<p>&nbsp;</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;System;<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;HelpAttribute&nbsp;:&nbsp;Attribute<br /><br />{<br /><br />}<br /></span></div>
<p align="left">不管你是否相信我，就这样我们就已经创建了一个自定义</span><span lang="EN-US">attribute</span><span>。现在就可以用它来装饰我们的类了，就像我们使用</span><span lang="EN-US">obsolete attribute</span><span>一样。</span><span lang="EN-US"> </span></p>
<p align="left">&nbsp;</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #000000">[Help()]<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;AnyClass<br /><br />{<br /><br />}<br /></span></div>
<p align="left">&nbsp;</p>
<p align="left"><span>注意：按惯例我们是用</span><span lang="CS">&#8221;Attribute&#8220;</span><span>作为</span><span lang="CS">attribute</span><span>类名的后缀，然而，当我们当我们把</span><span lang="CS">attribute</span><span>绑定到某语言元素时，是不包含</span><span lang="CS">&#8220;Attribute&#8220;</span><span>后缀的。编译器首先在</span><span lang="EN-US"><span style="color: #993300"><span lang="EN-US">System.Attribute</span><span lang="EN-US"> </span></span></span><span>的继承类中查找该</span><span lang="CS">attribute</span><span>，如果没有找到，编译器会把</span><span lang="CS">&#8220;Attribute&#8220;</span><span>追加到该</span><span lang="CS">attribute</span><span>的名字后面，然后查找它。</span><span lang="EN-US"> </span></p>
<p align="left"><span>但是迄今为止，该</span><span lang="EN-US">attribute</span><span>没有任何用处。为了使它有点用处，让我们在它里面加点东西吧。</span><span lang="EN-US"> </span></p>
<p><span lang="EN-US">&nbsp;</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;System;<br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;HelpAttribute&nbsp;:&nbsp;Attribute<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;HelpAttribute(String&nbsp;Descrition_in)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.description&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;Description_in;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">protected</span><span style="color: #000000">&nbsp;String&nbsp;description;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;Description&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">get</span><span style="color: #000000">&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.description;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;<br />}<br />[Help(</span><span style="color: #000000">"</span><span style="color: #000000">this&nbsp;is&nbsp;a&nbsp;do-nothing&nbsp;class</span><span style="color: #000000">"</span><span style="color: #000000">)]<br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;AnyClass<br />{<br />}<br /></span></div>
<p></span></p>
<p><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span>&nbsp;<span>在上面的例子中，我们在</span><span lang="CS">attribute</span><span>类中添加了一个属性，在最后一节中，我们将在运行时查询该属性。</span></p>
<p align="left"><strong><span style="color: #ff9900"><strong><span>定义或控制自定义</span></strong><strong><span lang="CS">Attribute</span></strong><strong><span>的用法</span></strong></span></strong></p>
<p align="left"><span lang="CS">AttributeUsage</span><span lang="CS"> </span><span>类是另一预定义类</span><span>（<span style="color: #008080"><span>译者注：</span><span lang="CS">attribute</span><span>类本身用这个</span><span lang="CS">atrribute </span><span lang="CS">System.AttributeUsage</span><span>来标记</span></span></span><span>）</span><span>，它将帮助我们控制我们自定义</span><span lang="CS">attribute</span><span>的用法，这就是，我们能为自定义的</span><span lang="CS">attribute</span><span>类定义</span><span lang="CS">attributes</span><span>。</span><span lang="CS"> </span></p>
<p align="left"><span>它描述了一个自定义</span><span lang="CS">attribute</span><span>类能被怎样使用。</span></p>
<p align="left"><span lang="CS">AttributeUsage</span><span lang="CS"> </span><span>提供三个属性，我们能将它们放置到我们的自定义</span><span lang="CS">attribute</span><span>类上，</span><span> </span><span>第一个特性是：</span><span lang="CS"> </span></p>
<p align="left"><strong><span lang="EN-US">ValidOn</span></strong></p>
<p align="left"><span>通过这个属性，我们能指定我们的自定义</span><span lang="EN-US">attribute</span><span>可以放置在哪些语言元素之上。这组我们能把自定义</span><span lang="EN-US">attribute</span><span>类放置其上的语言元素被放在枚举器</span><span lang="EN-US">AttributeTargets</span><span lang="EN-US"> </span><span>中。我们可以使用</span><span lang="EN-US">bitwise（<span style="color: #008080">译者注：这个词不知道怎么翻译好，但他的意思是可以这么用<span style="color: #99ccff"><span style="color: #000000">：</span></span></span><span style="color: #99ccff"><span style="color: #000000">[AttributeUsage<span style="color: #ff0000"><span style="color: #000000"><span style="color: #000000">(</span></span>(</span><span style="color: #ff0000">AttributeTargets)4</span>,&nbsp;AllowMultiple</span>&nbsp;<span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">,&nbsp;Inherited&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">&nbsp;)],<span style="color: #ff0000">4</span><span style="color: #008080">代表就是</span>&#8220;<span style="color: #ff0000">class</span>&#8221;<span style="color: #008080">元素，其它诸如<span style="color: #ff0000">1</span>代表&#8220;<span style="color: #ff0000">assembly</span>&#8221;，<span style="color: #ff0000">16383</span>代表&#8220;<span style="color: #ff0000">all</span>&#8221;等等</span>）</span></span></span><span>或者</span><span lang="EN-US">&#8221;.&#8221;</span><span>操做符绑定几个</span><span lang="EN-US">AttributeTargets</span><span lang="EN-US"> </span><span>值。</span><span>（译者注：默认值为</span><span lang="EN-US">AttributeTargets.All</span><span lang="EN-US">)</span><span style="color: #ff0000" lang="EN-US"> </span></p>
<p align="left"><strong><span lang="EN-US">AllowMultiple</span></strong></p>
<p align="left"><span>该属性标识我们的自定义</span><span lang="EN-US">attribte</span><span>能在同一语言元素上使用多次。</span><span>（<span style="color: #008080"><span>译者注：该属性为</span><span lang="EN-US">bool</span><span>类型，默认值为</span><span lang="EN-US">false</span><span>，意思就是该自定义</span><span lang="EN-US">attribute</span><span>在同一语言元素上只能使用一次</span></span></span><span>）</span></p>
<p align="left"><span lang="EN-US"></span></p>
<p align="left"><strong><span lang="EN-US">Inherited</span></strong></p>
<p align="left"><span>我们可以使用该属性来控制我们的自定义</span><span lang="EN-US">attribute</span><span>类的继承规则。该属性标识我们的自定义</span><span lang="EN-US">attribute</span><span>是否可以由派生类继承。（</span><span>（译者注：该属性为</span><span lang="EN-US">bool</span><span>类型，默认值为</span><span lang="EN-US">false</span><span>，意思是不能继承）</span></p>
<p align="left"><span>让我们来做点实际的东西吧，我们将把</span><span lang="EN-US">AttributeUsage</span><span lang="EN-US"> attribute </span><span>放置在我们的</span><span lang="EN-US">help attribute </span><span>上并在它的帮助下，我们来控制</span><span lang="EN-US">help attribute</span><span>的用法。</span></p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;System;<br /><br />[AttributeUsage(AttributeTargets.Class,&nbsp;AllowMultiple&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">,&nbsp;Inherited&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">&nbsp;)]<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;HelpAttribute&nbsp;:&nbsp;Attribute<br /><br />{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;HelpAttribute(String&nbsp;Description_in)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.description&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;Description_in;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">protected</span><span style="color: #000000">&nbsp;String&nbsp;description;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;Description<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">get</span><span style="color: #000000">&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.description;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;<br /><br />}<br /><br /></span></div>
<p>首先我们注意</span><span> </span><span lang="CS">AttributeTargets.Class</span><span lang="CS">. </span><span>它规定这个</span><span lang="CS">help attribute </span><span>只能放置在语言元素</span><span lang="CS">&#8221;class&#8221;</span><span>之上。这就意味着，下面的代码将会产生一个错误。</span><span> </span></p><span lang="EN-US"><span style="background-color: #ffcc00">
<p><span lang="EN-US">AnyClass.cs: Attribute 'Help' is not valid on this declaration type. <br /></span><span lang="EN-US">It is valid on 'class' declarations only.</span></p></span></span>
<p><span lang="EN-US">现在试着把它绑定到方法。</span><span lang="CS"><span></p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #000000">[Help(</span><span style="color: #000000">"</span><span style="color: #000000">this&nbsp;is&nbsp;a&nbsp;do-nothing&nbsp;class</span><span style="color: #000000">"</span><span style="color: #000000">)]<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;AnyClass<br /><br />{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;[Help(</span><span style="color: #000000">"</span><span style="color: #000000">this&nbsp;is&nbsp;a&nbsp;do-nothing&nbsp;method</span><span style="color: #000000">"</span><span style="color: #000000">)]&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">error</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;AnyMethod()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />}&nbsp;<br /></span></div>
<p>我们可以使用</span><span> </span><span lang="EN-US"><span style="color: #993300"><span lang="EN-US">AttributeTargets.All</span><span lang="EN-US"> </span></span></span><span>来允许</span><span lang="EN-US"> Help attribute </span><span>可以放置在任何预定义的语言元素上，那些可能的语言元素如下</span><span lang="EN-US">:&nbsp; </span></p>
<ul type="disc"><span lang="EN-US"><span style="background-color: #ff00ff">
<ul type="disc"><span lang="EN-US"><span lang="EN-US"><span style="background-color: #ffffff"><span lang="EN-US"><span lang="EN-US"><span style="color: #800080"><span lang="EN-US"><span lang="EN-US"><span style="background-color: #ffffff"><span lang="EN-US"><li><span lang="EN-US">Assembly,&nbsp;</span><span style="background-color: #ffffff" lang="EN-US"> </span></li><li><span lang="EN-US">Module,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">Class,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">Struct,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">Enum,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">Constructor,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">Method,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">Property,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">Field,</span><span lang="EN-US"> </span></li><li><span lang="EN-US">Event,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">Interface,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">Parameter,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">Delegate,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">All = Assembly | Module | Class | Struct | Enum | Constructor | Method | Property | Field | Event | Interface | Parameter | Delegate,</span><span lang="EN-US"> </span></li><li><span lang="EN-US">ClassMembers = Class | Struct | Enum | Constructor | Method | Property | Field | Event | Delegate | Interface )</span><span lang="EN-US"> </span></span></span></span></span></span></span></span></span></span></span></li></ul></span></li><li>~</span><span>现在考虑下</span><span> </span><span lang="EN-US"><span style="color: #ff00ff"><span lang="EN-US">AllowMultiple = </span><span lang="EN-US">false</span></span></span><span lang="EN-US">. </span><span>这就规定该</span><span lang="EN-US"> attribute </span><span>不能在同一语言元素上放置多次</span><span lang="EN-US">. </span></li></ul>
<p><span lang="CS">
<p><span lang="CS"></span></p><span>
<p>&nbsp;</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #000000">[Help(</span><span style="color: #000000">"</span><span style="color: #000000">this&nbsp;is&nbsp;a&nbsp;do-nothing&nbsp;class</span><span style="color: #000000">"</span><span style="color: #000000">)]<br /><br />[Help(</span><span style="color: #000000">"</span><span style="color: #000000">it&nbsp;contains&nbsp;a&nbsp;do-nothing&nbsp;method</span><span style="color: #000000">"</span><span style="color: #000000">)]<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;AnyClass<br /><br />{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;[Help(</span><span style="color: #000000">"</span><span style="color: #000000">this&nbsp;is&nbsp;a&nbsp;do-nothing&nbsp;method</span><span style="color: #000000">"</span><span style="color: #000000">)]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">error</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;AnyMethod()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />}<br /></span></div>
<p>它产生了一个编译错误：</span><span> </span></p>
<p><span style="background-color: #ff9900" lang="EN-US">AnyClass.cs: Duplicate 'Help' attribute</span></p>
<p><span lang="EN-US">Ok</span><span>！现在我们该讨论下最后那个属性了，</span><span lang="EN-US">&#8221;Inherited&#8221;, </span><span>指出当把该</span><span lang="EN-US">attribute</span><span>放置于一个基类之上，是否派生类也继承了该</span><span lang="EN-US">attribute</span><span>。如果绑定至某个</span><span lang="EN-US">attribute</span><span>类的</span><span lang="EN-US">&#8221;Inherited&#8221;</span><span>被设为</span><span lang="EN-US">true,</span><span>那么该</span><span lang="EN-US">attribute</span><span>就会被继承，然而如果绑定至某个</span><span lang="EN-US">attribute</span><span>类的</span><span lang="EN-US">&#8221;Inherited&#8221;</span><span>被设为</span><span lang="EN-US">false</span><span>或者没有定义，那么该</span><span lang="EN-US">attribute</span><span>就不会被继承。</span><span> </span></p>
<p><span>让我们假设有如下的类关系。</span><span lang="EN-US"> </span></p>
<p>
<p><span lang="CS"></span></p><span>
<p>&nbsp;</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #000000">[Help(</span><span style="color: #000000">"</span><span style="color: #000000">BaseClass</span><span style="color: #000000">"</span><span style="color: #000000">)]&nbsp;<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Base<br /><br />{<br /><br />}<br /><br />&nbsp;<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Derive&nbsp;:&nbsp;&nbsp;Base<br /><br />{<br /><br />}<br /></span></div>
<p>我们有四种可能的绑定</span><span lang="EN-US">: </span></p>
<ul type="disc"><span lang="EN-US"><span style="background-color: #ff9900"></li><li><span lang="EN-US">[AttributeUsage(AttributeTargets.Class, AllowMultiple = </span><span lang="EN-US">false</span><span lang="EN-US">, Inherited = </span><span lang="EN-US">false</span><span lang="EN-US"> )]&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">[AttributeUsage(AttributeTargets.Class, AllowMultiple = </span><span lang="EN-US">true</span><span lang="EN-US">, Inherited = </span><span lang="EN-US">false)</span><span lang="EN-US"> ]&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">[AttributeUsage(AttributeTargets.Class, AllowMultiple = </span><span lang="EN-US">false</span><span lang="EN-US">, Inherited = </span><span lang="EN-US">true</span><span lang="EN-US"> )]&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">[AttributeUsage(AttributeTargets.Class, AllowMultiple = </span><span lang="EN-US">true</span><span lang="EN-US">, Inherited = </span><span lang="EN-US">true)</span><span lang="EN-US"> ]&nbsp;</span><span lang="EN-US"> </span></span></span></li></ul>
<p><strong><span>第一种情况</span></strong><strong></strong></p>
<p><span>如果我们查询（我们将在后面来了解如何在运行时来查询</span><span lang="EN-US">attributes</span><span>）派生类中的</span><span lang="EN-US">help attribute</span><span>，我们将不可能查询到因为</span><span lang="EN-US">&#8221;Inherited&#8221;</span><span>被设为了</span><span lang="EN-US">false</span><span>。</span><span lang="EN-US"> </span></p>
<p><strong><span>第二种情况</span></strong><strong></strong></p>
<p><span>第二种情况没有什么不同，因为其</span><span lang="EN-US">&#8221;Inherited&#8221;</span><span>也被设为了</span><span lang="EN-US">false</span><span>。</span><span lang="EN-US"> </span></p>
<p><strong><span>第三种情况</span></strong><strong></strong></p>
<p><span>为了解释第三种和第四种情况，让我们为派生类也绑定同一</span><span lang="EN-US">attribute</span><span>。</span><span lang="EN-US"> </span></p>
<p>
<p><span lang="CS"></span></p><span>
<p>&nbsp;</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #000000">[Help(</span><span style="color: #000000">"</span><span style="color: #000000">BaseClass</span><span style="color: #000000">"</span><span style="color: #000000">)]&nbsp;<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Base<br /><br />{<br /><br />}<br /><br />[Help(</span><span style="color: #000000">"</span><span style="color: #000000">DeriveClass</span><span style="color: #000000">"</span><span style="color: #000000">)]&nbsp;<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Derive&nbsp;:&nbsp;&nbsp;Base<br /><br />{<br /><br />}<br /></span></div>
<p style="color: #ff9900">现在我们查询相关的</span><span lang="CS">help attribute </span><span>，我们将仅仅可以得到派生类的</span><span lang="CS">attribute</span><span>，为什么这样是因为</span><span lang="CS">help attribute</span><span>虽然允许被继承，但不能多次在同一语言元素上使用，所以基类中的</span><span lang="CS">help attribute</span><span>被派生类的</span><span lang="CS">help attribute </span><span>重写了。</span><span> </span></p>
<p><strong><span>第四种情况</span></strong><strong></strong></p>
<p><span>在第四种情况中，当我们查询派生类的</span><span lang="CS">help attribute </span><span>时，我们可以得到两个</span><span lang="CS">attributes</span><span>，当然是因为</span><span lang="CS">help attribute</span><span>既允许被继承，又允许在同一语言元素上多次使用的结果。</span><span lang="CS"> </span></p>
<p><span>注意：</span><span lang="CS">AttributeUsage</span><span lang="CS"> attribute </span><span>仅应用在那种是</span><span lang="CS">System.Attribute</span><span lang="CS"> </span><span>派生的</span><span lang="CS">attriubte</span><span>类而且绑定值该</span><span lang="CS">attriubte</span><span>类的</span><span lang="CS">AllowMultiple</span><span>和</span><span lang="CS">Inherited</span><span>均为</span><span lang="CS">false</span><span>上才是有效的。</span><span lang="CS"> </span></p>
<p><strong><span style="color: #ff9900"><strong><span>可选参数</span></strong><strong><span lang="CS"> vs. </span></strong><strong><span>命名参数</span></strong></span></strong></p>
<p><span>可选参数是</span><span lang="EN-US">attribute</span><span>类构造函数的参数。它们是强制的，必须在每次在</span><span lang="EN-US">attribute</span><span>绑定至某语言元素时提供一个值。而另一方面，命名参数倒是真正的可选参数，不是在</span><span lang="EN-US">attribute</span><span>构造函数的参数。</span><span lang="EN-US"> </span></p>
<p><span>为了更加详细的解释，让我们在</span><span lang="EN-US">Help</span><span>类中添加另外的属性。</span><span lang="EN-US"> </span></p>
<p><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS">
<p><span lang="CS"></span></p><span>
<p>&nbsp;</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #000000">[AttributeUsage(AttributeTargets.Class,&nbsp;AllowMultiple&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">,<br /><br />&nbsp;Inherited&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">)]<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;HelpAttribute&nbsp;:&nbsp;Attribute<br /><br />{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;HelpAttribute(String&nbsp;Description_in)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.description&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;Description_in;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.verion&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">No&nbsp;Version&nbsp;is&nbsp;defined&nbsp;for&nbsp;this&nbsp;class</span><span style="color: #000000">"</span><span style="color: #000000">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">protected</span><span style="color: #000000">&nbsp;String&nbsp;description;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;Description<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">get</span><span style="color: #000000">&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.description;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">protected</span><span style="color: #000000">&nbsp;String&nbsp;version;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;Version<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">get</span><span style="color: #000000">&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.version;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">if&nbsp;we&nbsp;ever&nbsp;want&nbsp;our&nbsp;attribute&nbsp;user&nbsp;to&nbsp;set&nbsp;this&nbsp;property,&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">we&nbsp;must&nbsp;specify&nbsp;set&nbsp;method&nbsp;for&nbsp;it&nbsp;</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">set</span><span style="color: #000000">&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.verion&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;value;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />}<br /><br />[Help(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;Class1</span><span style="color: #000000">"</span><span style="color: #000000">)]<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Class1<br /><br />{<br /><br />}<br /><br />&nbsp;<br /><br />[Help(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;Class2</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;Version&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">1.0</span><span style="color: #000000">"</span><span style="color: #000000">)]<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Class2<br /><br />{<br /><br />}<br /><br />&nbsp;<br /><br />[Help(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;Class3</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;Version&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">2.0</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;<br /><br />&nbsp;Description&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;do-nothing&nbsp;class</span><span style="color: #000000">"</span><span style="color: #000000">)]<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Class3<br /><br />{<br /><br />}<br /></span></div>
<p>当我们在</span><span lang="CS">Class1</span><span>中查询</span><span lang="CS">Help attribute</span><span>已经它的属性，我们将得到：</span><span> </span></p><span lang="EN-US"><span style="background-color: #ff9900">
<p><span lang="EN-US">Help.Description : This is Class1</span></p>
<p><span lang="EN-US">Help.Version :No Version is defined for this class</span></p></span></span>
<p><span>因为我们没有为</span><span lang="EN-US">Version</span><span>这个属性定义任何任何值，所以在构造函数中设定的值被我们查询出来了。如果没有定义任何值，那么就会赋一个该类型的默认值（例如：如果是</span><span lang="EN-US">int</span><span>型，默认值就是</span><span lang="EN-US">0</span><span>）。</span><span> </span></p>
<p><span>现在，查询</span><span lang="EN-US">Class2</span><span>的结果是：</span><span lang="EN-US"> </span></p><span lang="EN-US"><span style="background-color: #ff9900">
<p><span lang="EN-US">Help.Description : This is Class2</span></p>
<p><span lang="EN-US">Help.Version :<span>&nbsp; </span>1.0</span></p></span></span>
<p><span>我们不能为了可选参数而使用多个构造函数，应该用已命名参数来代替。我们之所以称它们为已命名的，是因为当我们在构造函数为它们提供值时，我们必须命名它们。例如，在第二个类中，我们如是定义</span><span lang="EN-US">Help</span><span>。</span><span> </span></p>
<p><span lang="CS">[Help(</span><span lang="CS">"This is Class2"</span><span lang="CS">, Version = </span><span lang="CS">"1.0"</span><span lang="CS">)]</span></p>
<p><span>在</span><span lang="CS"> AttributeUsage </span><span>例子中</span><span lang="CS">, </span><span>参数</span><span lang="CS">&#8221;ValidOn&#8221;</span><span>是可选参数，而</span><span lang="CS">&#8220;Inherited&#8220;</span><span>和</span><span lang="CS">&#8220;AllowMultiple&#8220; </span><span>是命名参数。</span><span> </span></p>
<p><span>注意：为了在</span><span lang="CS">attribute</span><span>的构造函数中设定命名参数的值，我们必须为相应的属性提供一个</span><span lang="CS">set</span><span>方法否则会引起编译期错误：</span><span lang="CS"> </span></p>
<p><span style="background-color: #ff9900" lang="EN-US">'Version' : Named attribute argument can't be a read only property</span></p>
<p><span>现在，我们在</span><span lang="EN-US">Class3</span><span>中查找</span><span lang="EN-US">Help attribute </span><span>及其属性会发生什么呢？结果是跟上面提到的相同的编译期错误。</span><span> </span></p>
<p><span style="background-color: #ff9900" lang="EN-US">'Desciption' : Named attribute argument can't be a read only property</span></p>
<p><span>现在我们修改下</span><span lang="EN-US">Help</span><span>类，为属性</span><span lang="EN-US">&#8221;Description&#8221;</span><span>加一个</span><span lang="EN-US">set</span><span>方法。现在的输出就是：</span><span> </span></p><span lang="EN-US"><span style="background-color: #ff9900">
<p><span lang="EN-US">Help.Description : This is do-nothing class </span></p>
<p><span lang="EN-US">Help.Version : 2.0</span></p></span></span>
<p><span>在屏幕后面究竟发生了什么呢？首先带有可选参数的构造函数被调用，然后，每个命名参数的</span><span lang="EN-US">set</span><span>方法被调用，在构造函数中赋给命名参数的值被</span><span lang="EN-US">set</span><span>方法所覆写。</span><span> </span></p>
<p><strong><span>参数类型</span></strong><strong></strong></p>
<p><span>一个</span><span lang="EN-US">attribute</span><span>类的参数类型被限定在如下类型中：</span><span lang="EN-US"> </span></p>
<ul type="disc"><span lang="EN-US"><span style="color: #ff00ff"></li><li><span lang="EN-US">bool</span><span lang="EN-US">,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">byte,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">char</span><span lang="EN-US">,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">double</span><span lang="EN-US">,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">float</span><span lang="EN-US">,</span><span lang="EN-US"> </span></li><li><span lang="EN-US">int</span><span lang="EN-US">,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">long</span><span lang="EN-US">,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">short</span><span lang="EN-US">,&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">string&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">System.Type&nbsp;</span><span lang="EN-US"> </span></li><li><span lang="EN-US">object&nbsp;</span><span lang="EN-US"> </span></li><li></span></span><span style="color: #ff0000" lang="EN-US">An enum type, provided that it and any types in which it is nested are publicly accessible. A one-dimensional array involving any of the types listed above&nbsp; </span></li></ul>
<p><strong><span lang="EN-US"><span style="color: #ff9900"><strong><span lang="EN-US">Attributes 标记</span></strong></span></span></strong></p>
<p><span>假设，我们想把</span><span lang="EN-US">Help attribute </span><span>绑定至元素</span><span lang="EN-US"> assembly</span><span>。第一个问题是我们要把</span><span lang="EN-US">Help attribute </span><span>放在哪儿才能让编译器确定该</span><span lang="EN-US">attribute</span><span>是绑定至整个</span><span lang="EN-US">assembly</span><span>呢？考虑另一种情况，我们想把</span><span lang="EN-US">attribute</span><span>绑定至一个方法的返回类型上，怎样才能让编译器确定我们是把</span><span lang="EN-US">attribute</span><span>绑定至方法的返回类型上，而不是整个方法呢？</span><span lang="EN-US"> </span></p>
<p><span>为了解决诸如此类的含糊问题，我们使用</span><span lang="EN-US">attribute</span><span>标识符，有了它的帮助，我们就可以确切地申明我们把</span><span lang="EN-US">attribute </span><span>绑定至哪一个语言元素。</span></p>
<p><span>例如</span><span lang="EN-US">: </span></p>
<p><span lang="CS"><span style="color: #999999"><span style="background-color: #999999; color: #000000" lang="CS">[<span style="color: #000000"><span lang="CS">assembly: Help(</span><span lang="CS">"this a do-nothing assembly"</span><span lang="CS">)]</span></span></span></span></span></p>
<p><span>这个在</span><span lang="CS">Help attribute </span><span>前的</span><span lang="CS">assembly</span><span>标识符确切地告诉编译器，该</span><span lang="CS">attribute</span><span>被绑定至整个</span><span lang="CS">assembly</span><span>。可能的标识符有：</span><span lang="CS">&nbsp; </span></p>
<ul type="disc"><span lang="EN-US"><span style="color: #ff00ff"></li><li><span lang="EN-US">assembly </span></li><li><span lang="EN-US">module </span></li><li><span lang="EN-US">type </span></li><li><span lang="EN-US">method </span></li><li><span lang="EN-US">property </span></li><li><span lang="EN-US">event </span></li><li><span lang="EN-US">field </span></li><li><span lang="EN-US">param </span></li><li><span lang="EN-US">return </span></span></span></li></ul>
<p><strong><span style="color: #ff9900"><strong><span>在运行时查询</span></strong><strong><span lang="EN-US">Attributes</span></strong></span></strong></p>
<p><span>现在我们明白怎么创建</span><span lang="EN-US">attribtes</span><span>和把它们绑定至语言元素。是时候来学习类的使用者该如何在运行时查询这信息。</span><span lang="EN-US"> </span></p>
<p><span>为了查询一语言元素上绑定的</span><span lang="EN-US">attributes</span><span>，我们必须使用反射。反射有能力在运行时发现类型信息。</span><span lang="EN-US"> </span></p>
<p><span>我们可以使用</span><span lang="EN-US">.NET Framework Reflection APIs </span><span>通过对整个</span><span lang="EN-US">assembly</span><span>元数据的迭代，列举出</span><span lang="EN-US">assembly</span><span>中所有已定义的类，类型，还有方法。</span></p>
<p><span>记住那旧的</span><span lang="EN-US">Help</span><span lang="EN-US"> attribute </span><span>和</span><span lang="EN-US">AnyClass</span><span lang="EN-US"> </span><span>类。</span><span lang="EN-US"> </span></p>
<p><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS">
<p><span lang="CS"></span></p><span>
<p>&nbsp;</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;System;<br /><br /></span><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;System.Reflection;<br /><br /></span><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;System.Diagnostics;<br /><br />&nbsp;<br /><br /></span><span style="color: #008000">//</span><span style="color: #008000">attaching&nbsp;Help&nbsp;attribute&nbsp;to&nbsp;entire&nbsp;assembly</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />[assembly&nbsp;:&nbsp;Help(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;Assembly&nbsp;demonstrates&nbsp;custom&nbsp;attributes&nbsp;</span><span style="color: #000000"><br /></span><span style="color: #000000"><br />&nbsp;creation&nbsp;and&nbsp;their&nbsp;run</span><span style="color: #000000">-</span><span style="color: #000000">time&nbsp;query.</span><span style="color: #000000">"</span><span style="color: #000000">)]</span><span style="color: #000000"><br /></span><span style="color: #000000"><br />&nbsp;<br /><br /></span><span style="color: #008000">//</span><span style="color: #008000">our&nbsp;custom&nbsp;attribute&nbsp;class</span><span style="color: #008000"><br /></span><span style="color: #000000"><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;HelpAttribute&nbsp;:&nbsp;Attribute<br /><br />{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;HelpAttribute(String&nbsp;Description_in)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000"><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;TODO:&nbsp;Add&nbsp;constructor&nbsp;logic&nbsp;here</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.description&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;Description_in;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//<br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">protected</span><span style="color: #000000">&nbsp;String&nbsp;description;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;Description<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">get</span><span style="color: #000000">&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.deescription;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;<br /><br />}<br /><br /></span><span style="color: #008000">//</span><span style="color: #008000">attaching&nbsp;Help&nbsp;attribute&nbsp;to&nbsp;our&nbsp;AnyClass</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />[HelpString(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;a&nbsp;do-nothing&nbsp;Class.</span><span style="color: #000000">"</span><span style="color: #000000">)]<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;AnyClass<br /><br />{<br /><br /></span><span style="color: #008000">//</span><span style="color: #008000">attaching&nbsp;Help&nbsp;attribute&nbsp;to&nbsp;our&nbsp;AnyMethod</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;[Help(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;a&nbsp;do-nothing&nbsp;Method.</span><span style="color: #000000">"</span><span style="color: #000000">)]<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;AnyMethod()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br /></span><span style="color: #008000">//</span><span style="color: #008000">attaching&nbsp;Help&nbsp;attribute&nbsp;to&nbsp;our&nbsp;AnyInt&nbsp;Field</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;[Help(</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;any&nbsp;Integer.</span><span style="color: #000000">"</span><span style="color: #000000">)]<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;AnyInt;<br /><br />}<br /><br /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;QueryApp<br /><br />{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Main()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />}<br /></span></div>
<p>我们将在接下来的两节中在我们的</span><span lang="EN-US">Main</span><span>方法中加入</span><span lang="EN-US">attribute</span><span>查询代码。</span><span> </span></p>
<p><strong><span style="color: #ff9900"><strong><span>查询程序集的</span></strong><strong><span lang="EN-US">Attributes</span></strong></span></strong></p>
<p><span>在接下来的代码中，我们先得到当前的进程名称，然后用</span><span lang="EN-US">Assembly</span><span>类中的</span><span lang="EN-US">LoadForm</span><span>（）方法加载程序集，再有用</span><span lang="EN-US">GetCustomAttributes</span><span>（）方法得到被绑定至当前程序集的自定义</span><span lang="EN-US">attributes</span><span>，接下来用</span><span lang="EN-US">foreach</span><span>语句遍历所有</span><span lang="EN-US">attributes</span><span>并试图把每个</span><span lang="EN-US">attribute</span><span>转型为</span><span lang="EN-US">Help attribute</span><span>（即将转型的对象使用</span><span lang="EN-US">as</span><span>关键字有一个优点，就是当转型不合法时，我们将不需担心会抛出异常，代之以空值（</span><span lang="EN-US">null</span><span>）作为结果），接下来的一行就是检查转型是否有效，及是不是为空，跟着就显示</span><span lang="EN-US">Help attribute</span><span>的&#8220;</span><span lang="EN-US">Description</span><span>&#8221;属性。</span><span lang="EN-US"> </span></p>
<p><span lang="CS"><span lang="CS"><span lang="CS">
<p><span lang="CS"></span></p><span>
<p>&nbsp;</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;QueryApp<br /><br />{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Main()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HelpAttribute&nbsp;HelpAttr;<br /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">Querying&nbsp;Assembly&nbsp;Attributes</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;assemblyName;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Process&nbsp;p&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;Process.GetCurrentProcess();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assemblyName&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;p.ProcessName&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">.exe</span><span style="color: #000000">"</span><span style="color: #000000">;<br /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Assembly&nbsp;a&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;Assembly.LoadFrom(assemblyName);<br /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">foreach</span><span style="color: #000000">&nbsp;(Attribute&nbsp;attr&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;a.GetCustomAttributes(</span><span style="color: #0000ff">true</span><span style="color: #000000">))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HelpAttr&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;attr&nbsp;</span><span style="color: #0000ff">as</span><span style="color: #000000">&nbsp;HelpAttribute;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">null</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;HelpAttr)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="color: #000000">"</span><span style="color: #000000">Description&nbsp;of&nbsp;{0}:\n{1}</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assemblyName,HelpAttr.Description);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />}<br /><br />}<br /></span></div>
<p>程序输出如下：</span><span> </span></p><span lang="EN-US"><span style="background-color: #ff9900">
<p><span lang="EN-US">Description of QueryAttribute.exe:</span></p>
<p><span lang="EN-US">This Assembly demonstrates custom attributes creation and </span></p>
<p><span lang="EN-US">their run-time query.</span></p>
<p><span lang="EN-US">Press any key to continue</span></p></span></span>
<p><strong><span style="color: #ff9900"><strong><span>查询类、方法、类成员的</span></strong><strong><span lang="EN-US">Attributes</span></strong></span></strong></p>
<p><span>下面的代码中，我们惟一不熟悉的就是</span><span lang="EN-US">Main</span><span>（）方法中的第一行。</span><span lang="EN-US"> </span></p>
<p><span lang="CS">Type type = </span><span lang="CS">typeof</span><span lang="CS">(AnyClass);</span></p>
<p><span>它用</span><span lang="EN-US">typeof</span><span>操作符得到了一个与我们</span><span lang="EN-US">AnyClass</span><span>类相关联的</span><span lang="EN-US">Type</span><span>型对象。剩下的查询类</span><span lang="EN-US">attributes</span><span>代码就与上面的例子是相似的，应该不要解释了吧（我是这么想的）。</span><span> </span></p>
<p><span>为查询方法和类成员的</span><span lang="EN-US">attributes,</span><span>首先我们得到所有在类中存在的方法和成员，然后我们查询与它们相关的所有</span><span lang="EN-US">attributes</span><span>，这就跟我们查询类</span><span lang="EN-US">attributes</span><span>一样的方式。</span><span lang="EN-US"> </span></p>
<p><span lang="CS"><span lang="CS"><span lang="CS"><span lang="EN-US"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS"><span lang="CS">
<p><span lang="CS"></span></p><span lang="EN-US"><span style="background-color: #ff9900"><span lang="EN-US">
<p>&nbsp;</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;QueryApp<br /><br />{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Main()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type&nbsp;type&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">typeof</span><span style="color: #000000">(AnyClass);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HelpAttribute&nbsp;HelpAttr;<br /><br />&nbsp;<br /><br />&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">Querying&nbsp;Class&nbsp;Attributes</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">foreach</span><span style="color: #000000">&nbsp;(Attribute&nbsp;attr&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;type.GetCustomAttributes(</span><span style="color: #0000ff">true</span><span style="color: #000000">))<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HelpAttr&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;attr&nbsp;</span><span style="color: #0000ff">as</span><span style="color: #000000">&nbsp;HelpAttribute;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">null</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;HelpAttr)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="color: #000000">"</span><span style="color: #000000">Description&nbsp;of&nbsp;AnyClass:\n{0}</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HelpAttr.Description);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">Querying&nbsp;Class-Method&nbsp;Attributes&nbsp;&nbsp;</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">foreach</span><span style="color: #000000">(MethodInfo&nbsp;method&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;type.GetMethods())<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">foreach</span><span style="color: #000000">&nbsp;(Attribute&nbsp;attr&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;method.GetCustomAttributes(</span><span style="color: #0000ff">true</span><span style="color: #000000">))<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HelpAttr&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;attr&nbsp;</span><span style="color: #0000ff">as</span><span style="color: #000000">&nbsp;HelpAttribute;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">null</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;HelpAttr)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="color: #000000">"</span><span style="color: #000000">Description&nbsp;of&nbsp;{0}:\n{1}</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method.Name,&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HelpAttr.Description);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">Querying&nbsp;Class-Field&nbsp;(only&nbsp;public)&nbsp;Attributes</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">foreach</span><span style="color: #000000">(FieldInfo&nbsp;field&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;type.GetFields())<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">foreach</span><span style="color: #000000">&nbsp;(Attribute&nbsp;attr&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;field.GetCustomAttributes(</span><span style="color: #0000ff">true</span><span style="color: #000000">))<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HelpAttr</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;attr&nbsp;</span><span style="color: #0000ff">as</span><span style="color: #000000">&nbsp;HelpAttribute;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">null</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;HelpAttr)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="color: #000000">"</span><span style="color: #000000">Description&nbsp;of&nbsp;{0}:\n{1}</span><span style="color: #000000">"</span><span style="color: #000000">,<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;field.Name,HelpAttr.Description);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />}<br /></span></div>
<p>The output of the following program is. </span></p>
<p><span lang="EN-US">Description of AnyClass:</span></p>
<p><span lang="EN-US">This is a do-nothing Class.</span></p>
<p><span lang="EN-US">Description of AnyMethod:</span></p>
<p><span lang="EN-US">This is a do-nothing Method.</span></p>
<p><span lang="EN-US">Description of AnyInt:</span></p>
<p><span lang="EN-US">This is any Integer.</span></p>
<p><span lang="EN-US">Press any key to continue</span></p></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>  <img src="http://www.cnblogs.com/glacierh/aggbug/1521445.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/glacierh/archive/2009/07/11/1521445.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/glacierh/archive/2009/07/11/1521445.html#commentform" target="_blank">发表评论</a></p><p><a href="http://job.cnblogs.com/" target="_blank">找优秀程序员，就在博客园</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/59187/" target="_blank">Notifo推iPhone应用：弥补邮件推送缺陷</a><span style="color:gray">(2010-03-19 21:04)</span><br/>· <a href="http://news.cnblogs.com/n/59186/" target="_blank">分析：微软IE9现身 网络视频标准争议依旧未解</a><span style="color:gray">(2010-03-19 20:57)</span><br/>· <a href="http://news.cnblogs.com/n/59185/" target="_blank">连线朱骏：陈晓薇离开九城与魔兽无关</a><span style="color:gray">(2010-03-19 20:52)</span><br/>· <a href="http://news.cnblogs.com/n/59184/" target="_blank">九城总裁陈晓薇5月期满离任 朱骏将代理总裁</a><span style="color:gray">(2010-03-19 20:48)</span><br/>· <a href="http://news.cnblogs.com/n/59183/" target="_blank">Google携手Intel和Sony推出&quot;Google电视&quot;</a><span style="color:gray">(2010-03-19 20:44)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/59093/" target="_blank">[视频]想做你的Code</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>Windows Mobile 代码中最小化窗口</title><link>http://www.cnblogs.com/glacierh/archive/2009/01/12/1374304.html</link><dc:creator>Glacier</dc:creator><author>Glacier</author><pubDate>Mon, 12 Jan 2009 08:23:00 GMT</pubDate><guid>http://www.cnblogs.com/glacierh/archive/2009/01/12/1374304.html</guid><description><![CDATA[<p>阅读: 576 评论: 0 作者: <a href="http://www.cnblogs.com/glacierh/" target="_blank">Glacier</a> 发表于 2009-01-12 16:23 <a href="http://www.cnblogs.com/glacierh/archive/2009/01/12/1374304.html" target="_blank">原文链接</a></p><p>在Windows Mobile 中，窗体类Form的属性WindowState可以设置窗体的状态，但枚举类型FormWindowState只有Maximized（最大化）和Normal（正常），而没有最小化。以下的代码可以实现窗体最小化的功能，从面对窗口进行隐藏。</p>
<div class="cnblogs_code"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[DllImport(</span><span style="color: #800000">"</span><span style="color: #800000">coredll</span><span style="color: #800000">"</span><span style="color: #000000">)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">extern</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">bool</span><span style="color: #000000">&nbsp;ShowWindow(IntPtr&nbsp;hwnd,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;nCmdShow);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;SW_MINIMIZE&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #800080">6</span><span style="color: #000000">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;mitHide_Click(</span><span style="color: #0000ff">object</span><span style="color: #000000">&nbsp;sender,&nbsp;EventArgs&nbsp;e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowWindow(</span><span style="color: #0000ff">this</span><span style="color: #000000">.Handle,&nbsp;SW_MINIMIZE);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span></div>
<img src="http://www.cnblogs.com/glacierh/aggbug/1374304.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/glacierh/archive/2009/01/12/1374304.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/glacierh/archive/2009/01/12/1374304.html#commentform" target="_blank">发表评论</a></p><p><a href="http://job.cnblogs.com/" target="_blank">找优秀程序员，就在博客园</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/59187/" target="_blank">Notifo推iPhone应用：弥补邮件推送缺陷</a><span style="color:gray">(2010-03-19 21:04)</span><br/>· <a href="http://news.cnblogs.com/n/59186/" target="_blank">分析：微软IE9现身 网络视频标准争议依旧未解</a><span style="color:gray">(2010-03-19 20:57)</span><br/>· <a href="http://news.cnblogs.com/n/59185/" target="_blank">连线朱骏：陈晓薇离开九城与魔兽无关</a><span style="color:gray">(2010-03-19 20:52)</span><br/>· <a href="http://news.cnblogs.com/n/59184/" target="_blank">九城总裁陈晓薇5月期满离任 朱骏将代理总裁</a><span style="color:gray">(2010-03-19 20:48)</span><br/>· <a href="http://news.cnblogs.com/n/59183/" target="_blank">Google携手Intel和Sony推出&quot;Google电视&quot;</a><span style="color:gray">(2010-03-19 20:44)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/59093/" target="_blank">[视频]想做你的Code</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item></channel></rss>