<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_Ben</title><subtitle type="text"/><id>http://feed.cnblogs.com/blog/u/28182/rss</id><updated>2011-06-01T09:51:49Z</updated><author><name>Benguo</name><uri>http://www.cnblogs.com/aspnetcsharp/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aspnetcsharp/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/28182/rss"/><entry><id>http://www.cnblogs.com/aspnetcsharp/archive/2010/07/21/1782179.html</id><title type="text">jQuery常见问题整理 新手必读（转自jQuery中文社区）</title><summary type="text">Q1,js的写法:document.getElementById('save').disabled=true;在jquery中我是这样写的$("#save").disabled = true; 为什么没效果呢A,这个是典型的问题，其实因为$("#save")出来的其实是jQuery对象，而不是普通DOM对象这是新手常见的问题。解决方法有2：1，用JQ写法，$("#save").attr("disa...</summary><published>2010-07-21T06:36:00Z</published><updated>2010-07-21T06:36:00Z</updated><author><name>Benguo</name><uri>http://www.cnblogs.com/aspnetcsharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aspnetcsharp/archive/2010/07/21/1782179.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aspnetcsharp/archive/2010/07/21/1782179.html"/><content type="html">&lt;p&gt;Q1,js的写法:document.getElementById('save').disabled=true;&lt;br /&gt;在jquery中我是这样写的$("#save").disabled = true;&amp;nbsp; 为什么没效果呢&lt;/p&gt;&#xD;
&lt;p&gt;A,这个是典型的问题，其实因为$("#save")出来的其实是jQuery对象，而不是普通DOM对象&lt;br /&gt;这是新手常见的问题。&lt;br /&gt;解决方法有2：&lt;br /&gt;1，用JQ写法，$("#save").attr("disabled","true");&lt;br /&gt;2，转成DOM写法$("#save")[0].disabled=true;&lt;br /&gt;当然，$("#save")[0]也可以写成$("#save").get(0)。他返回的也是DOM元素&lt;/p&gt;&#xD;
&lt;p&gt;$("#save").eq(0)得到的还是jq对象&lt;br /&gt;$(dom对象)就能得到一个jq对象。&lt;/p&gt;&#xD;
&lt;p&gt;Q2,获取选中的checkbox&lt;br /&gt;A:&lt;br /&gt;获取所有选中的checkbox:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $("input:checkbox:checked")&lt;br /&gt;判断是否一组checkbox都选中了:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if($("input:checkbox:checked").length){}&lt;br /&gt;判断某一个checkbox是否被选中&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if($("input:checkbox").is(":checked")){}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;Q3,我的id里有[]或.之类的符号，怎么办？或者带有命名空间的xml标签带有:怎么办？&lt;br /&gt;A:用\\来转义如&amp;lt;div id="id[1]"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;$("#id\\[1\\]")&lt;/p&gt;&#xD;
&lt;p&gt;Q4，在框架页中，如何操作父窗口的对象&lt;br /&gt;A，引用UPC的方法&lt;/p&gt;&#xD;
&lt;p&gt;没找到很好的方法&lt;br /&gt;只好用DOM方法与jquery方法结合的方式实现了&lt;/p&gt;&#xD;
&lt;p&gt;1.在父窗口中操作 选中IFRAME中的所有单选钮&lt;br /&gt;$(window.frames["iframe1"].document).find("input[type='radio']").attr("checked","true");&lt;/p&gt;&#xD;
&lt;p&gt;2.在IFRAME中操作 选中父窗口中的所有单选钮&lt;br /&gt;$(window.parent.document).find("input[type='radio']").attr("checked","true");&lt;/p&gt;&#xD;
&lt;p&gt;iframe框架的：&amp;lt;iframe src="test.html" id="iframe1" width="700" height="300" frameborder="0" scrolling="auto"&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;IE7中测试通过 回去你自己试试吧&lt;/p&gt;&#xD;
&lt;p&gt;实现的原理其实很简单 就是用到了$(DOM对象)可以转换成jquery对象&lt;br /&gt;==================================================&lt;/p&gt;&#xD;
&lt;p&gt;不过我的方法是&lt;br /&gt;window.parent.jQuery("input[name=validate]").val("&amp;lt;%=Session("GetCode")%&amp;gt;");&lt;br /&gt;这段是来自我博客的自动填写验证码的，有兴趣可分析下我的FOOTER里的那个框架。&lt;br /&gt;其实本质上和UPC的方法是一样的。大家可以借鉴参考&lt;/p&gt;&#xD;
&lt;p&gt;Q5,解析由AJAX加载的XML，和相关乱码问题&lt;br /&gt;A:见之前的帖子：&lt;a href="http://bbs.jquery.org.cn/read.php?tid-1673.html"&gt;http://bbs.jquery.org.cn/read.php?tid-1673.html&lt;/a&gt;&lt;br /&gt;Q6，我下了一个插件Interface，怎么在最新的jQuery里一点都不好用？&lt;br /&gt;A: Interface已经被完全重写并且改名为jQuery UI，可以在这里找到最新版本：&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://ui.jquery.com/"&gt;http://ui.jquery.com/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Q7，在IE下动画会闪一下，效果不理想&lt;br /&gt;A，加上DTD定义即可&lt;br /&gt;比如&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""&lt;a href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&lt;/a&gt;"&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;Q8，为什么官方的说&lt;br /&gt;Download jQuery 1.2.3 (15kb, Minified and Gzipped)，但我下在下来却有&lt;br /&gt;jquery-1.2.3.min.js&amp;nbsp;&amp;nbsp; 52.8 KB &lt;br /&gt;A，显然，他是用了Gzip了（一种服务器端压缩技术，自己GOOGLE）。而不是官网写错了没更新或者是骗人的~&lt;/p&gt;&#xD;
&lt;p&gt;Q9，pack,min和原版三个版本什么区别呢？&lt;br /&gt;pack是如果服务器没开启gzip的时候用&lt;br /&gt;min是服务器有开gzip的时候用&lt;br /&gt;原版可以用于平时开发的时候，或者自己分析源码用。&lt;/p&gt;&#xD;
&lt;p&gt;Q10,jQuery用的是什么压缩软件？&lt;br /&gt;A: Dean Edwards 写的Packer &lt;a href="http://dean.edwards.name/packer/"&gt;http://dean.edwards.name/packer/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Q11,$('a[@href^="mailto"]') 这个代码在jQuery 1.3里不能用，1.2里可以，为什么？&lt;br /&gt;A:&amp;nbsp; jQuery 1.3以后已经不需要再使用那个@符号了，只需要简单的去掉那个@符号就可以正常运作了。&lt;/p&gt;&#xD;
&lt;p&gt;本文来自: PQ秀秀网(&lt;a href="http://www.pqshow.com/"&gt;http://www.pqshow.com/&lt;/a&gt;) 详细出处参考：&lt;a href="http://www.pqshow.com/design/Javascript/200909/10372.html"&gt;http://www.pqshow.com/design/Javascript/200909/10372.html&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/aspnetcsharp/aggbug/1782179.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aspnetcsharp/archive/2010/07/21/1782179.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aspnetcsharp/articles/1768436.html</id><title type="text">jquery.validate使用攻略 - 4</title><summary type="text">自定义错误消息的显示方式默认情况下，验证提示信息用label元素来显示, 并且会添加css class, 通过css可以很方便设置出错控件以及错误信息的显示方式。/* 输入控件验证出错*/form input.error { border:solid 1px red;}/* 验证错误提示信息*/form label.error{width: 200px;margin-left: 10px; col...</summary><published>2010-06-30T08:00:00Z</published><updated>2010-06-30T08:00:00Z</updated><author><name>Benguo</name><uri>http://www.cnblogs.com/aspnetcsharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aspnetcsharp/articles/1768436.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aspnetcsharp/articles/1768436.html"/><content type="html">自定义错误消息的显示方式&lt;br /&gt;&lt;br /&gt;默认情况下，验证提示信息用label元素来显示, 并且会添加css class, 通过css可以很方便设置出错控件以及错误信息的显示方式。&lt;br /&gt;&lt;br /&gt;/* 输入控件验证出错*/&lt;br /&gt;form&amp;nbsp; input.error { border:solid 1px red;}&lt;br /&gt;&lt;br /&gt;/* 验证错误提示信息*/&lt;br /&gt;form label.error{width: 200px;margin-left: 10px; color: Red;}&lt;br /&gt;&lt;br /&gt;如果想自定义显示方式，可以修改jquery.validate的默认显示方式&lt;br /&gt;&lt;br /&gt;默认用label显示错误消息，可以通过errorElement属性来修改&lt;br /&gt;errorElement: 错误消息的html标签&lt;br /&gt;&lt;br /&gt;$(".selector").validate&lt;br /&gt;&amp;nbsp;&amp;nbsp; errorElement: "em"&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;可以在出错信息外用其他的元素包装一层。&lt;br /&gt;wrapper: 错误消息的外层封装html标签&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp;&amp;nbsp; wrapper: "li"&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;验证出错的css class默认是error，通过errorClass可以修改&lt;br /&gt;errorClass: 验证出错时使用的css class&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp;&amp;nbsp; errorClass: "invalid"&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;还自定义验证成功时的动作&lt;br /&gt;success: 如果值是字符串，会当做一个css类，如果是一个函数，则执行该函数&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;success: "valid"&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;或者&lt;br /&gt;&lt;br /&gt;success: function(label) {&lt;br /&gt;label.html(" ").addClass("checked");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;还可以把错误消息统一到一个容器显示&lt;br /&gt;errorLabelContainer: 将错误消息统一到一个容器显示&lt;br /&gt;&lt;br /&gt;$("#myform").validate({&lt;br /&gt;&amp;nbsp;&amp;nbsp; errorLabelContainer: "#messageBox"&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;默认情况下，错误消息是放在验证元素后面的，可以自定义错误消息的显示位置&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp; errorPlacement: function(error, element) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; error.appendTo( element.parent("td").next("td") );&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;更进一步可以定义一个组，把几个地方的出错信息统一放在一个地方，用error Placement控制把出错信息放在哪里&lt;br /&gt;groups：定义一个组&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp; groups: {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; username: "fname lname"&lt;br /&gt;&amp;nbsp; },&lt;br /&gt;&amp;nbsp; errorPlacement: function(error, element) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (element.attr("name") == "fname" || element.attr("name") == "lname" )&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; error.insertAfter("#lastname");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; error.insertAfter(element);&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;高亮显示&lt;br /&gt;highlight: 高亮显示，默认是添加errorClass&lt;br /&gt;unhighlight: 和highlight对应，反高亮显示&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp; highlight: function(element, errorClass) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(element).addClass(errorClass);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(element.form).find("label[for=" + element.id + "]").addClass(errorClass);&lt;br /&gt;&amp;nbsp; },&lt;br /&gt;&amp;nbsp; unhighlight: function(element, errorClass) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(element).removeClass(errorClass);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $(element.form).find("label[for=" + element.id + "]").removeClass(errorClass);&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;或者可以完全自定义错误显示&lt;br /&gt;showErrors: 得到错误的显示句柄&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp;&amp;nbsp; showErrors: function(errorMap, errorList) {&lt;br /&gt;$("#summary").html("Your form contains " + this.numberOfInvalids() &lt;br /&gt;+ " errors, see details below.");&lt;br /&gt;this.defaultShowErrors();&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;})&lt;img src="http://www.cnblogs.com/aspnetcsharp/aggbug/1768436.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aspnetcsharp/articles/1768436.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aspnetcsharp/articles/1768438.html</id><title type="text">jquery.validate使用攻略 - 5</title><summary type="text">一些常用的验证脚本不会写js了，只能从网上找一些常用的验证脚本。// 手机号码验证jQuery.validator.addMethod("mobile", function(value, element) { var length = value.length; var mobile = /^(((13[0-9]{1})|(15[0-9]{1}))+\d{8})$/ return this.opt...</summary><published>2010-06-30T08:00:00Z</published><updated>2010-06-30T08:00:00Z</updated><author><name>Benguo</name><uri>http://www.cnblogs.com/aspnetcsharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aspnetcsharp/articles/1768438.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aspnetcsharp/articles/1768438.html"/><content type="html">一些常用的验证脚本&lt;br /&gt;&lt;br /&gt;不会写js了，只能从网上找一些常用的验证脚本。&lt;br /&gt;&lt;br /&gt;// 手机号码验证&lt;br /&gt;jQuery.validator.addMethod("mobile", function(value, element) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var length = value.length;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var mobile =&amp;nbsp; /^(((13[0-9]{1})|(15[0-9]{1}))+\d{8})$/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this.optional(element) || (length == 11 &amp;amp;&amp;amp; mobile.test(value));&lt;br /&gt;}, "手机号码格式错误");&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;br /&gt;// 电话号码验证&amp;nbsp;&amp;nbsp; &lt;br /&gt;jQuery.validator.addMethod("phone", function(value, element) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var tel = /^(0[0-9]{2,3}\-)?([2-9][0-9]{6,7})+(\-[0-9]{1,4})?$/;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this.optional(element) || (tel.test(value));&lt;br /&gt;}, "电话号码格式错误");&lt;br /&gt;&lt;br /&gt;// 邮政编码验证&amp;nbsp;&amp;nbsp; &lt;br /&gt;jQuery.validator.addMethod("zipCode", function(value, element) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var tel = /^[0-9]{6}$/;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this.optional(element) || (tel.test(value));&lt;br /&gt;}, "邮政编码格式错误");&lt;br /&gt;&lt;br /&gt;// QQ号码验证&amp;nbsp;&amp;nbsp; &lt;br /&gt;jQuery.validator.addMethod("qq", function(value, element) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var tel = /^[1-9]\d{4,9}$/;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this.optional(element) || (tel.test(value));&lt;br /&gt;}, "qq号码格式错误");&lt;br /&gt;&lt;br /&gt;// IP地址验证&lt;br /&gt;jQuery.validator.addMethod("ip", function(value, element) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var ip = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this.optional(element) || (ip.test(value) &amp;amp;&amp;amp; (RegExp.$1 &amp;lt; 256 &amp;amp;&amp;amp; RegExp.$2 &amp;lt; 256 &amp;amp;&amp;amp; RegExp.$3 &amp;lt; 256 &amp;amp;&amp;amp; RegExp.$4 &amp;lt; 256));&lt;br /&gt;}, "Ip地址格式错误");&lt;br /&gt;&lt;br /&gt;// 字母和数字的验证&lt;br /&gt;jQuery.validator.addMethod("chrnum", function(value, element) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var chrnum = /^([a-zA-Z0-9]+)$/;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this.optional(element) || (chrnum.test(value));&lt;br /&gt;}, "只能输入数字和字母(字符A-Z, a-z, 0-9)");&lt;br /&gt;&lt;br /&gt;// 中文的验证&lt;br /&gt;jQuery.validator.addMethod("chinese", function(value, element) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var chinese = /^[\u4e00-\u9fa5]+$/;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this.optional(element) || (chinese.test(value));&lt;br /&gt;}, "只能输入中文");&lt;br /&gt;&lt;br /&gt;// 下拉框验证&lt;br /&gt;$.validator.addMethod("selectNone", function(value, element) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return value == "请选择";&lt;br /&gt;}, "必须选择一项");&lt;br /&gt;&lt;br /&gt;// 字节长度验证&lt;br /&gt;jQuery.validator.addMethod("byteRangeLength", function(value, element, param) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var length = value.length;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (var i = 0; i &amp;lt; value.length; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (value.charCodeAt(i) &amp;gt; 127) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; length++;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return this.optional(element) || (length &amp;gt;= param[0] &amp;amp;&amp;amp; length &amp;lt;= param[1]);&lt;br /&gt;}, $.validator.format("请确保输入的值在{0}-{1}个字节之间(一个中文字算2个字节)"));&lt;img src="http://www.cnblogs.com/aspnetcsharp/aggbug/1768438.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aspnetcsharp/articles/1768438.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aspnetcsharp/articles/1768431.html</id><title type="text">jquery.validate使用攻略 - 3</title><summary type="text">自定义jquery-validate的验证行为1: 自定义表单提交设置submitHandler来自定义表单提交动作$(".selector").validate({ submitHandler: function(form) { alert("验证通过"); }});如果需要提交表单，可以调用form.submit(); 或者$(form).ajaxSubmit();2: 调试模式将debug设...</summary><published>2010-06-30T07:58:00Z</published><updated>2010-06-30T07:58:00Z</updated><author><name>Benguo</name><uri>http://www.cnblogs.com/aspnetcsharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aspnetcsharp/articles/1768431.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aspnetcsharp/articles/1768431.html"/><content type="html">自定义jquery-validate的验证行为&lt;br /&gt;&lt;br /&gt;1: 自定义表单提交&lt;br /&gt;&lt;br /&gt;设置submitHandler来自定义表单提交动作&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; submitHandler: function(form) { alert("验证通过"); }&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;如果需要提交表单，可以调用&lt;br /&gt;form.submit(); 或者$(form).ajaxSubmit();&lt;br /&gt;&lt;br /&gt;2: 调试模式&lt;br /&gt;&lt;br /&gt;将debug设置为true，表单不会提交，只进行检查，方便调试&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp;&amp;nbsp; debug: true&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;3: 设置validate的默认值&lt;br /&gt;&lt;br /&gt;使用setDefaults可以设置validate的默认值，比如默认所有表单验证都是在debug模式下进行&lt;br /&gt;&lt;br /&gt;$.validator.setDefaults({&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; debug: true&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;4: 某些元素不验证&lt;br /&gt;&lt;br /&gt;设置ignore属性可以忽略某些元素不验证&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp;&amp;nbsp; ignore: "ignore"&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;5: 验证时机&lt;br /&gt;&lt;br /&gt;jquery.validate可以很方便的设置在什么时候触发验证动作&lt;br /&gt;&lt;br /&gt;onsubmit: 提交时是否验证&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp;&amp;nbsp; onsubmit: false&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;onfocusout: 失去焦点时验证(checkboxes/radio除外)&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp;&amp;nbsp; onfocusout: false&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;onkeyup: 在keyup时验证&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp;&amp;nbsp; onkeyup: false&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;onclick: 在checkboxes、radio点击时验证.&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp;&amp;nbsp; onclick: false&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;6: 重写验证规则和验证提示信息&lt;br /&gt;&lt;br /&gt;//重写max的的验证提示信息&lt;br /&gt;$.validator.messages.max = jQuery.format("Your totals musn't exceed {0}!");&lt;br /&gt;&lt;br /&gt;//重写equal方法&lt;br /&gt;$.validator.methods.equal = function(value, element, param) {&lt;br /&gt;return value == param;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;7: focusInvalid 是否把焦点聚焦在最后一个动作或者最近的一次出错上&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp;&amp;nbsp; focusInvalid: false&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;8: focusCleanup&lt;br /&gt;&lt;br /&gt;如果该属性设置为True, 那么控件获得焦点时，移除出错的class定义，隐藏错误信息，避免和 focusInvalid.一起用。&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp;&amp;nbsp; focusCleanup: true&lt;br /&gt;})&lt;br /&gt;&lt;br /&gt;9: meta&lt;br /&gt;&lt;br /&gt;设置meta来封装验证规则&lt;br /&gt;&lt;br /&gt;$(".selector").validate({&lt;br /&gt;&amp;nbsp;&amp;nbsp; meta: "validate",&lt;br /&gt;})&lt;img src="http://www.cnblogs.com/aspnetcsharp/aggbug/1768431.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aspnetcsharp/articles/1768431.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aspnetcsharp/articles/1768429.html</id><title type="text">jquery.validate使用攻略-2</title><summary type="text"/><published>2010-06-30T07:56:00Z</published><updated>2010-06-30T07:56:00Z</updated><author><name>Benguo</name><uri>http://www.cnblogs.com/aspnetcsharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aspnetcsharp/articles/1768429.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aspnetcsharp/articles/1768429.html"/><content type="html">&lt;pre&gt;jQuery.validate.js API说明&#xD;
&#xD;
参考&lt;a href="http://ideabean.javaeye.com%3cstrong%3eplugin/" target="_blank"&gt;http://ideabean.javaeye.com%3cstrong%3eplugin/&lt;/a&gt;&lt;strong&gt;Plugin methods&lt;/strong&gt;&lt;/pre&gt;&lt;pre&gt;Name	Type&#xD;
&#xD;
validate( options )	Returns: Validator&#xD;
验证所选的FORM&#xD;
&#xD;
valid( )	Returns: Boolean&#xD;
检查是否验证通过&#xD;
&#xD;
rules( )	Returns: Options&#xD;
返回元素的验证规则&#xD;
&#xD;
rules( "add", rules )	Returns: Options&#xD;
增加验证规则&#xD;
&#xD;
rules( "remove", rules )	Returns: Options&#xD;
删除验证规则&#xD;
&#xD;
removeAttrs( attributes )	Returns: Options&#xD;
删除特殊属性并且返回他们&#xD;
&#xD;
&lt;strong&gt;Custom selectors&lt;/strong&gt;&#xD;
Name	Type&#xD;
&#xD;
:blank	Returns: Array &amp;lt;Element &amp;gt;&#xD;
没有值的筛选器&#xD;
&#xD;
:filled	Returns: Array &amp;lt;Element &amp;gt;&#xD;
有值的筛选器&#xD;
&#xD;
:unchecked	Returns: Array &amp;lt;Element &amp;gt;&#xD;
没选择的元素的筛选器&#xD;
&#xD;
&lt;strong&gt;Utilities&lt;/strong&gt;&#xD;
&#xD;
Name	Type&#xD;
&#xD;
jQuery.format( template, argument , argumentN... )	Returns: String&#xD;
用参数代替模板中的 {n}。&#xD;
&#xD;
&lt;strong&gt;Validator&lt;/strong&gt;&lt;/pre&gt;&lt;pre&gt;validate方法返回一个Validator对象, 它有很多方法， 让你能使用引发校验程序或者改变form的内容. &#xD;
&#xD;
下面只是列出常用的.&#xD;
&#xD;
form( )	Returns: Boolean&#xD;
验证form返回成功还是失败&#xD;
&#xD;
element( element )	Returns: Boolean&#xD;
验证单个元素是成功还是失败&#xD;
&#xD;
resetForm( )	Returns: undefined&#xD;
把前面验证的FORM恢复到验证前原来的状态&#xD;
&#xD;
showErrors( errors )	Returns: undefined&#xD;
显示特定的错误信息&#xD;
&#xD;
&lt;strong&gt;built-in Validation methods&lt;/strong&gt;&#xD;
&#xD;
Name	Type&#xD;
&#xD;
setDefaults( defaults )	Returns: undefined&#xD;
改变默认的设置&#xD;
&#xD;
addMethod( name, method, message )	Returns: undefined&#xD;
添加一个新的验证方法. 必须包括名字，一个JAVASCRIPT方法和一个默认的信息&#xD;
&#xD;
addClassRules( name, rules )	Returns: undefined&#xD;
增加组合验证类型 &#xD;
&#xD;
addClassRules( rules )	Returns: undefined&#xD;
增加组合验证类型 &#xD;
&#xD;
&lt;strong&gt;built-in Validation methods&lt;/strong&gt;&lt;/pre&gt;&lt;pre&gt;Name	Type&#xD;
&#xD;
required( )	Returns: Boolean&#xD;
必填验证元素&#xD;
&#xD;
required( dependency-expression )	Returns: Boolean&#xD;
必填元素依赖于表达式的结果.&#xD;
&#xD;
required( dependency-callback )	Returns: Boolean&#xD;
必填元素依赖于回调函数的结果.&#xD;
&#xD;
remote( url )	Returns: Boolean&#xD;
请求远程校验。url通常是一个远程调用方法&#xD;
&#xD;
minlength( length )	Returns: Boolean&#xD;
设置最小长度&#xD;
&#xD;
maxlength( length )	Returns: Boolean&#xD;
设置最大长度&#xD;
&#xD;
rangelength( range )	Returns: Boolean&#xD;
设置一个长度范围[min,max]&#xD;
&#xD;
min( value )	Returns: Boolean&#xD;
设置最小值.&#xD;
&#xD;
max( value )	Returns: Boolean&#xD;
设置最大值.&#xD;
&#xD;
range( range )	Returns: Boolean&#xD;
设置值的范围&#xD;
&#xD;
email( )	Returns: Boolean&#xD;
验证电子邮箱格式&#xD;
&#xD;
url( )	Returns: Boolean&#xD;
验证连接格式&#xD;
&#xD;
date( )	Returns: Boolean&#xD;
验证日期格式(类似30/30/2008的格式，不验证日期准确性只验证格式)&#xD;
&#xD;
dateISO( )	Returns: Boolean&#xD;
研制ISO类型的日期格式&#xD;
&#xD;
dateDE( )	Returns: Boolean&#xD;
验证德式的日期格式（29.04.1994 or 1.1.2006）&#xD;
&#xD;
number( )	Returns: Boolean&#xD;
验证十进制数字（包括小数的）&#xD;
&#xD;
numberDE( )	Returns: Boolean&#xD;
Makes the element require a decimal number with german format.&#xD;
&#xD;
digits( )	Returns: Boolean&#xD;
验证整数&#xD;
&#xD;
creditcard( )	Returns: Boolean&#xD;
验证信用卡号&#xD;
&#xD;
accept( extension )	Returns: Boolean&#xD;
验证相同后缀名的字符串&#xD;
&#xD;
equalTo( other )	Returns: Boolean&#xD;
验证两个输入框的内容是否相同&#xD;
&#xD;
其他API参考下一章的自定义部分。&lt;/pre&gt;&lt;img src="http://www.cnblogs.com/aspnetcsharp/aggbug/1768429.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aspnetcsharp/articles/1768429.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aspnetcsharp/articles/1768424.html</id><title type="text">jquery.validate使用攻略-1</title><summary type="text"/><published>2010-06-30T07:52:00Z</published><updated>2010-06-30T07:52:00Z</updated><author><name>Benguo</name><uri>http://www.cnblogs.com/aspnetcsharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aspnetcsharp/articles/1768424.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aspnetcsharp/articles/1768424.html"/><content type="html">&lt;pre&gt;jquery.validate使用攻略&#xD;
&#xD;
好几年不写JS了，资料整理起来比较慢，格式也有点乱&#xD;
&#xD;
主要分几部分&#xD;
jquery.validate 基本用法&#xD;
jquery.validate API说明&#xD;
jquery.validate 自定义&#xD;
jquery.validate 常见类型的验证代码&#xD;
&#xD;
&lt;strong&gt;下载地址&lt;/strong&gt;&#xD;
&#xD;
jquery.validate插件的文档地址&#xD;
http://docs.jquery.com/Plugins/Validation&#xD;
&#xD;
jquery.validate插件的主页&#xD;
http://bassistance.de/jquery-plugins/jquery-plugin-validation/&#xD;
&#xD;
jquery.validate插件主页上提供的demo&#xD;
http://jquery.bassistance.de/validate/demo/&#xD;
&#xD;
&lt;strong&gt;验证规则&lt;/strong&gt;&lt;/pre&gt;&lt;pre&gt;下面是默认校验规则，也可以自定义规则&#xD;
&#xD;
(1)required:true 必输字段&#xD;
(2)remote:"check.php" 使用ajax方法调用check.php验证输入值&#xD;
(3)email:true 必须输入正确格式的电子邮件&#xD;
(4)url:true 必须输入正确格式的网址&#xD;
(5)date:true 必须输入正确格式的日期&#xD;
(6)dateISO:true 必须输入正确格式的日期(ISO)，例如：2009-06-23，1998/01/22 只验证格式，不验证有效性&#xD;
(7)number:true 必须输入合法的数字(负数，小数)&#xD;
(8)digits:true 必须输入整数&#xD;
(9)creditcard: 必须输入合法的信用卡号&#xD;
(10)equalTo:"#field" 输入值必须和#field相同&#xD;
(11)accept: 输入拥有合法后缀名的字符串（上传文件的后缀）&#xD;
(12)maxlength:5 输入长度最多是5的字符串(汉字算一个字符)&#xD;
(13)minlength:10 输入长度最小是10的字符串(汉字算一个字符)&#xD;
(14)rangelength:[5,10] 输入长度必须介于 5 和 10 之间的字符串")(汉字算一个字符)&#xD;
(15)range:[5,10] 输入值必须介于 5 和 10 之间&#xD;
(16)max:5 输入值不能大于5&#xD;
(17)min:10 输入值不能小于10&#xD;
&#xD;
&lt;strong&gt;验证提示&lt;/strong&gt;&#xD;
&#xD;
下面是默认的验证提示，官网有简体中文版的验证提示下载，或者通过jQuery.extend(jQuery.validator.messages自定义错误提示信息，可以将网站的验证提示文本统一到一个文件里。&#xD;
&#xD;
required: "This field is required.",&#xD;
remote: "Please fix this field.",&#xD;
email: "Please enter a valid email address.",&#xD;
url: "Please enter a valid URL.",&#xD;
date: "Please enter a valid date.",&#xD;
dateISO: "Please enter a valid date (ISO).",&#xD;
number: "Please enter a valid number.",&#xD;
digits: "Please enter only digits",&#xD;
creditcard: "Please enter a valid credit card number.",&#xD;
equalTo: "Please enter the same value again.",&#xD;
accept: "Please enter a value with a valid extension.",&#xD;
maxlength: $.validator.format("Please enter no more than {0} characters."),&#xD;
minlength: $.validator.format("Please enter at least {0} characters."),&#xD;
rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),&#xD;
range: $.validator.format("Please enter a value between {0} and {1}."),&#xD;
max: $.validator.format("Please enter a value less than or equal to {0}."),&#xD;
min: $.validator.format("Please enter a value greater than or equal to {0}.")&#xD;
&#xD;
&lt;strong&gt;使用方式&lt;/strong&gt;&#xD;
&#xD;
1：&#xD;
在控件中使用默认验证规则，例子：&#xD;
电子邮件(必填) &lt;/pre&gt;&lt;pre&gt;&amp;lt;input id="email"  value="email@" /&amp;gt;&lt;/pre&gt;&lt;pre&gt;2：&#xD;
可以在控件中自定义验证规则，例子：&#xD;
自定义(必填,[3,5])&#xD;
&amp;lt;input id="complex" value="hi"  /&amp;gt;&#xD;
&#xD;
3:&#xD;
&#xD;
通过javascript自定义验证规则，下面的JS自定义了两个规则，password和confirm_password&#xD;
$().ready(function() {&#xD;
    $("#form2").validate({&#xD;
        rules: {&#xD;
            password: {&#xD;
                required: true,&#xD;
                minlength: 5&#xD;
            },&#xD;
            confirm_password: {&#xD;
                required: true,&#xD;
                minlength: 5,&#xD;
                equalTo: "#password"&#xD;
            }&#xD;
        },&#xD;
        messages: {&#xD;
            password: {&#xD;
                required: "没有填写密码",&#xD;
                minlength: jQuery.format("密码不能小于{0}个字符")&#xD;
            },&#xD;
            confirm_password: {&#xD;
                required: "没有确认密码",&#xD;
                minlength: "确认密码不能小于{0}个字符",&#xD;
                equalTo: "两次输入密码不一致嘛"&#xD;
            }&#xD;
        }&#xD;
    });&#xD;
});&#xD;
    &#xD;
required除了设置为true/false之外，还可以使用表达式或者函数，比如&#xD;
$("#form2").validate({&#xD;
	rules: {&#xD;
		funcvalidate: {&#xD;
			required: function() {return $("#password").val()!=""; }&#xD;
		}&#xD;
	},&#xD;
	messages: {&#xD;
		funcvalidate: {&#xD;
			required: "有密码的情况下必填"&#xD;
		}&#xD;
	}&#xD;
});&#xD;
 &#xD;
Html&#xD;
密码&amp;lt;input id="password" name="password" type="password" /&amp;gt;&#xD;
确认密码&amp;lt;input id="confirm_password" name="confirm_password" type="password" /&amp;gt;&#xD;
条件验证&amp;lt;input id="funcvalidate" name="funcvalidate" value="" /&amp;gt;&#xD;
&#xD;
4：&#xD;
&#xD;
使用meta自定义验证信息&#xD;
&#xD;
首先用JS设置meta&#xD;
$("#form3").validate({ meta: "validate" });            &#xD;
&#xD;
Html&#xD;
&#xD;
email&amp;lt;input /&amp;gt;&#xD;
&#xD;
5:&#xD;
&#xD;
使用meta可以将验证规则写在自定义的标签内，比如validate&#xD;
&#xD;
JS设置meta&#xD;
$().ready(function() {&#xD;
    $.metadata.setType("attr", "validate");&#xD;
    $("#form1").validate();&#xD;
});&#xD;
&#xD;
Html&#xD;
&#xD;
Email&#xD;
&amp;lt;input id="email" name="email" &#xD;
validate="{required:true, email:true, messages:{required:'输入email地址', email:'你输入的不是有效的邮件地址'}}" /&amp;gt;&#xD;
&#xD;
6:&#xD;
自定义验证规则&#xD;
&#xD;
对于复杂的验证，可以通过jQuery.validator.addMethod添加自定义的验证规则&#xD;
&#xD;
官网提供的additional-methods.js里包含一些常用的验证方式，比如lettersonly，ziprange，nowhitespace等&#xD;
&#xD;
例子&#xD;
// 字符验证   &#xD;
jQuery.validator.addMethod("userName", function(value, element) {&#xD;
    return this.optional(element) || /^[\u0391-\uFFE5\w]+$/.test(value);&#xD;
}, "用户名只能包括中文字、英文字母、数字和下划线");   &#xD;
&#xD;
//然后就可以使用这个规则了&#xD;
$("#form1").validate({&#xD;
    // 验证规则&#xD;
    rules: {&#xD;
        userName: {&#xD;
            required: true,&#xD;
            userName: true,&#xD;
            rangelength: [5,10]&#xD;
        }&#xD;
    },&#xD;
    /* 设置错误信息 */&#xD;
    messages: {&#xD;
        userName: {&#xD;
            required: "请填写用户名",&#xD;
            rangelength: "用户名必须在5-10个字符之间" &#xD;
        }                &#xD;
    },&#xD;
});  &#xD;
&#xD;
7:&#xD;
radio、checkbox、select的验证方式类似&#xD;
&#xD;
radio的验证&#xD;
            &#xD;
性别&#xD;
&amp;lt;span&amp;gt;&#xD;
	男&amp;lt;input type="radio" id="gender_male" value="m" name="gender" /&amp;gt;&amp;lt;br /&amp;gt;&#xD;
	女&amp;lt;input type="radio" id="gender_female" value="f" name="gender" /&amp;gt;&#xD;
&amp;lt;/span&amp;gt;&#xD;
            &#xD;
checkbox的验证&#xD;
&#xD;
最少选择两项&#xD;
&amp;lt;span&amp;gt;&#xD;
	选项1&amp;lt;input type="checkbox" id="check_1" value="1" name="checkGroup" &#xD;
  /&amp;gt;&amp;lt;br /&amp;gt;&#xD;
	选项2&amp;lt;input type="checkbox" id="check_2" value="2" name="checkGroup" /&amp;gt;&amp;lt;br /&amp;gt;&#xD;
	选项3&amp;lt;input type="checkbox" id="check_3" value="3" name="checkGroup" /&amp;gt;&amp;lt;br /&amp;gt;&#xD;
&amp;lt;/span&amp;gt;&#xD;
&#xD;
select的验证&#xD;
&#xD;
下拉框&#xD;
&amp;lt;span&amp;gt;&#xD;
    &amp;lt;select id="selectbox" name="selectbox" &amp;gt;&#xD;
        &amp;lt;option value=""&amp;gt;&amp;lt;/option&amp;gt;&#xD;
        &amp;lt;option value="1"&amp;gt;1&amp;lt;/option&amp;gt;&#xD;
        &amp;lt;option value="2"&amp;gt;2&amp;lt;/option&amp;gt;&#xD;
        &amp;lt;option value="3"&amp;gt;3&amp;lt;/option&amp;gt;&#xD;
    &amp;lt;/select&amp;gt;&#xD;
&amp;lt;/span&amp;gt;&#xD;
8:&#xD;
&#xD;
Ajax验证&#xD;
&#xD;
用remote可以进行Ajax验证&#xD;
remote: {&#xD;
url: "url",&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //url地址&#xD;
type: "post",&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //发送方式&#xD;
dataType: "json",&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //数据格式&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; data: {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //要传递的数据&#xD;
	username: function() {&#xD;
		return $("#username").val();&#xD;
	}}&#xD;
}&#xD;
&#xD;
补充: jQuery Validation插件remote验证方式的Bug&#xD;
http://www.cnblogs.com/JeffreyZhao/archive/2009/12/04/jquery-validate-remote-bug.html&#xD;
&#xD;
下一章是API的具体说明&#xD;
然后整理怎么进一步自定义jQuery.validate以及网上一些常用的验证代码&lt;/pre&gt; &lt;img src="http://www.cnblogs.com/aspnetcsharp/aggbug/1768424.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aspnetcsharp/articles/1768424.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aspnetcsharp/articles/1762752.html</id><title type="text">ASP.NET MVC框架的面面观</title><summary type="text">前言写这篇文章的目的，是想总结一些东西，以帮助朋友们更好的使用这个框架。但是，我又不像把官方列举的哪些优势、功能翻译过来列举在这里。所以，我想干脆我就纯从个人观点上对这个框架评论一下吧。说的不好的，不对的还请批评指正。ASP.NET MVC&amp;#8212;&amp;#8212;螺旋进步的产物对于微软为什么要推出ASP.NET MVC，我们是无从得知的，也许是因为JavaEE平台上有Struts，也许是因为M...</summary><published>2010-06-22T08:15:00Z</published><updated>2010-06-22T08:15:00Z</updated><author><name>Benguo</name><uri>http://www.cnblogs.com/aspnetcsharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aspnetcsharp/articles/1762752.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aspnetcsharp/articles/1762752.html"/><content type="html">&lt;font size="4"&gt;&lt;span style="font-family: Arial; font-size: 10pt"&gt;前言&lt;/span&gt;&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&lt;span style="font-family: Arial; font-size: 10pt"&gt;写这篇文章的目的，是想总结一些东西，以帮助朋友们更好的使用这个框架。但是，我又不像把官方列举的哪些优势、功能翻译过来列举在这里。所以，我想干脆我就纯从个人观点上对这个框架评论一下吧。说的不好的，不对的还请批评指正。&lt;/span&gt;&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&lt;strong&gt;&lt;span style="font-family: Arial; font-size: 10pt"&gt;ASP.NET MVC&amp;#8212;&amp;#8212;螺旋进步的产物&lt;/span&gt;&lt;br /&gt;&#xD;
&lt;/strong&gt;&lt;br /&gt;&#xD;
&lt;span style="font-family: Arial; font-size: 10pt"&gt;对于微软为什么要推出ASP.NET MVC，我们是无从得知的，也许是因为JavaEE平台上有Struts，也许是因为MVC太流行，也许微软是想使得自己的Web App平台更完善，总之我们只能猜测。但是如果回顾一下微软的Web App平台进化过程，还是很有意思的。&lt;/span&gt;&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&lt;span style="font-family: Arial; font-size: 10pt"&gt;ASP&amp;#8212;&amp;#8212;微软最早为Web开发做出的贡献可能就是ASP了，这个动态语言把动态网页开发的难度空前降低了。但是，在很多人兴奋的用ASP写着一个又一个动态网页时，它的缺点渐渐暴露：语言过于简单，没有面向对象支持、没有好的IDE支持、&lt;/span&gt;&lt;span style="font-family: Arial; font-size: 10pt; text-decoration: underline"&gt;动态脚本和静态HTML杂糅在一起&lt;/span&gt;&lt;span style="font-family: Arial; font-size: 10pt"&gt;，使得修改及维护极为困难。&lt;/span&gt;&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&lt;span style="font-family: Arial; font-size: 10pt"&gt;Web Form&amp;#8212;&amp;#8212;说实话，即使是用现在的眼光看，微软推出的Web Form编程模型确实是很有创意，也很实用。&lt;/span&gt;&lt;span style="font-family: Arial; font-size: 10pt; text-decoration: underline"&gt;微软开创性地将桌面应用的开发模式引入Web应用开发&lt;/span&gt;&lt;span style="font-family: Arial; font-size: 10pt"&gt;：拖控件、写事件处理、运行...一切都那么美好，而且&lt;/span&gt;&lt;span style="font-family: Arial; font-size: 10pt; text-decoration: underline"&gt;前段静态代码和后端程序完全隔离在两个文件里&lt;/span&gt;&lt;span style="font-family: Arial; font-size: 10pt"&gt;，并且用户可以使用.NET平台上任意一种语言进行后端编程。对程序员来说，使用C#进行编程比使用ASP实在是舒服太多了。所以，Web Form模型可以说成为.NET Web App开发的代名词，所有基于.NET平台的Web开发人员都熟悉并接受了这种模型。&lt;/span&gt;&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
&lt;span style="font-family: Arial; font-size: 10pt"&gt;ASP.NET MVC&amp;#8212;&amp;#8212;就在Web Form大行其道时，微软推出了ASP.NET MVC。严格说，ASP.NET MVC和Web Form是不具有可比性的，Web Form是一个完整的新型模型，从顶层到底层是一整套的东西，而ASP.NET MVC只是给Web Form穿了件MVC样子的外套，它应该是基于Web Form的一种编程方式模型扩展。但是，从开发人员看，ASP.NET MVC的推出确实大大&lt;/span&gt;&lt;span style="font-family: Arial; font-size: 10pt; text-decoration: underline"&gt;改变了我们的开发方式&lt;/span&gt;&lt;span style="font-family: Arial; font-size: 10pt"&gt;，很多Web Form下的方式不被提倡了（你仍可以用，因为ASP.NET MVC也是基于Web Form的），例如，&lt;/span&gt;&lt;strong style="font-size: 10pt"&gt;曾饱受赞扬的服务器端控件再度被抛弃，转而再次使用客户端控件，事件驱动模型被抛弃，转而使用了类似传统的Url跳转处理模型。而且在数据验证等方式上与Web Form下提倡的方式有了很大变化&lt;/strong&gt;&lt;span style="font-size: 10pt"&gt;。&lt;/span&gt;&lt;br style="font-size: 10pt" /&gt;&#xD;
&lt;br style="font-size: 10pt" /&gt;&#xD;
&lt;span style="font-size: 10pt"&gt;如此看来，真像是一个轮回，似乎ASP.NET MVC又把我们带回到了ASP时代：服务器端模型不让用、事件驱动机制不让用、类似Desktop App的开发方式不让用...我们似乎从Web Form回到了传统的ASP时代。但是，真的是这样吗？当然不是！&lt;/span&gt;&lt;br style="font-size: 10pt" /&gt;&#xD;
&lt;br style="font-size: 10pt" /&gt;&#xD;
&lt;span style="font-size: 10pt"&gt;只要稍微用一下，就知道虽然ASP.NET MVC提倡我们废除Web Form下的很多东西和习惯，但是绝不是让我们&amp;#8220;回归原始&amp;#8221;，如果非要说是一个轮回，那也应该说是一个螺旋式的轮回，是上升式的轮回。&lt;/span&gt;&lt;br style="font-size: 10pt" /&gt;&#xD;
&lt;br style="font-size: 10pt" /&gt;&#xD;
&lt;span style="font-size: 10pt"&gt;记得马克思主义哲学中有个很经典的命题：对于新事物来说，道路是曲折的，前途是光明的。也许，Web App模型的发展就印证了这个观点吧。&lt;/span&gt;&lt;em style="font-size: 10pt"&gt;也许，服务器端控件、事件驱动模型这些东西一开始就是不适合Web App的，微软走了很多弯路，现在找到了正确的方向。&lt;/em&gt;&lt;span style="font-size: 10pt"&gt;抛弃的痛苦的，我们要抛弃曾经认为多么习惯并且倾注了大量心血的东西，但是，事物被否定后，剩下的的一个蜕变出的新事物，是一个更优秀的东西。&lt;/span&gt;&lt;br style="font-size: 10pt" /&gt;&#xD;
&lt;br style="font-size: 10pt" /&gt;&#xD;
&lt;span style="font-size: 10pt"&gt;例如，我们抛弃了用了多年的务器端控件、事件驱动模型&amp;#8230;&amp;#8230;但是我们得到了&lt;/span&gt;&lt;strong style="font-size: 10pt"&gt;低耦合的、关注被分离的、符合MVC模型的新的Web模型。要敢于否定，才能获得新生。微软是，我们也是。&lt;/strong&gt;&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
ASP.NET MVC带来的变化&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
下面，我们看看ASP.NET MVC到底让我们否定什么？又能得到什么。&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
1.服务器端表单控件。&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
由于ASP.NET MVC的特质，服务器端的表单控件不再被提倡使用，例如我们的文本框，不再使用asp:TextBox，而是使用传统的input，或直接让Html.TextBox生成。总之，很多服务器端控件被我们废止了。甚至GridView这样曾给我们带来无限快感的老朋友，也不再被提倡使用。但是，并不是说不能用任何服务器端控件，例如，为了实现母版，我们的ContentPlaceHolder还是必须要使用的。&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
2.事件驱动模型。&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
既然服务器端表单控件已经不提倡使用了，事件驱动模型自然也不被提倡，两者本来就是相辅相成的。在ASP.NET MVC中，当某个按钮被点击，你不要再习惯性想到应该在相应的aspx.cs中有个时间处理方法，你应该想到的是该有某个Controller中有个Action来处理这个事件。实际上，在ASP.NET MVC中，提倡不要在aspx.cs中写任何逻辑代码。甚至应该当他们不存在。&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
3.数据绑定&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
对于列表式表格数据，你一定习惯了GridView的数据绑定，可是，从你使用ASP.NET MVC开始，这不在被提倡了。你应该自己处理数据的显示。当然，我们也可以期待未来的ASP.NET MVC正式版中会有一个强大的Helper来帮我们做数据显示。&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
ASP.NET MVC的收益&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
你一定想知道，我们为使用ASP.NET付出了如此惨烈的代价，那么我们能得到什么？从我个人认为，你至少得到了以下东西：&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
1.清晰的、关注被分离的代码；&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
2.更容易的测试及维护；&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
3.更符合MVC的表示层；&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
4.你可以向Java程序员自豪的说：我现在也用MVC模式了，而且不用写任何XML！&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
总结&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
好了，到这里，这个系列就结束了。&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
在这个系列开篇里，我曾经说，我做这个系列的唯一目的只是让还徘徊在ASP.NET MVC门外的朋友快速入门，快速上手，快速学会使用这个框架做应用，所以，这个系列一直是在&amp;#8220;实用&amp;#8221;的指导思想下写的。它不够全面，没有涉及到ASP.NET MVC的方方面面。但是，我相信现在你已经有能力去自己学习那些&amp;#8220;方方面面&amp;#8221;了。当然，它也不够深入，没有讲解底层的原理。但是，现在的你一定也可以随着实践经验的基类，慢慢去研究它的原理了。&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
总之，只要你能通过这个系列的文章，学会使用ASP.NET MVC的基本方法，并已经开始试着做Demo了。那么，我的目的也就达到了。&lt;/font&gt; &lt;img src="http://www.cnblogs.com/aspnetcsharp/aggbug/1762752.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aspnetcsharp/articles/1762752.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aspnetcsharp/articles/1750630.html</id><title type="text">C# 中的委托和事件</title><summary type="text">引言委托 和 事件在 .Net Framework中的应用非常广泛，然而，较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。它们就像是一道槛儿，过了这个槛的人，觉得真是太容易了，而没有过去的人每次见到委托和事件就觉得心里别（bi&amp;#232;）得慌，混身不自在。本文中，我将通过两个范例由浅入深地讲述什么是委托、为什么要使用委托、事件的由来、.Net Framework中的委托和事件、委托和...</summary><published>2010-06-03T03:43:00Z</published><updated>2010-06-03T03:43:00Z</updated><author><name>Benguo</name><uri>http://www.cnblogs.com/aspnetcsharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aspnetcsharp/articles/1750630.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aspnetcsharp/articles/1750630.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&#xD;
&lt;p&gt;&lt;strong&gt;引言&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="font-size: 10pt"&gt;委托 和 事件在 .Net Framework中的应用非常广泛，然而，较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。它们就像是一道槛儿，过了这个槛的人，觉得真是太容易了，而没有过去的人每次见到委托和事件就觉得心里别（bi&amp;#232;）得慌，混身不自在。本文中，我将通过两个范例由浅入深地讲述什么是委托、为什么要使用委托、事件的由来、.Net Framework中的委托和事件、委托和事件对Observer设计模式的意义，对它们的中间代码也做了讨论。&lt;/span&gt;&lt;/p&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;将方法作为方法的参数&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;我们先不管这个标题如何的绕口，也不管委托究竟是个什么东西，来看下面这两个最简单的方法，它们不过是在屏幕上输出一句问候的话语：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; GreetPeople(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 做某些额外的事情，比如初始化之类，此处略&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; EnglishGreeting(name);&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; EnglishGreeting(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;"Morning, "&lt;/span&gt; + name);&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;暂且不管这两个方法有没有什么实际意义。GreetPeople用于向某人问好，当我们传递代表某人姓名的name参数，比如说&amp;#8220;Jimmy&amp;#8221;，进去的时候，在这个方法中，将调用EnglishGreeting方法，再次传递name参数，EnglishGreeting则用于向屏幕输出 &amp;#8220;Morning, Jimmy&amp;#8221;。&lt;/p&gt;&#xD;
&lt;p&gt;现在假设这个程序需要进行全球化，哎呀，不好了，我是中国人，我不明白&amp;#8220;Morning&amp;#8221;是什么意思，怎么办呢？好吧，我们再加个中文版的问候方法：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; ChineseGreeting(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;"早上好, "&lt;/span&gt; + name);&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;这时候，GreetPeople也需要改一改了，不然如何判断到底用哪个版本的Greeting问候方法合适呢？在进行这个之前，我们最好再定义一个枚举作为判断的依据：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;enum&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Language&lt;/span&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; English, Chinese&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; GreetPeople(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name, Language lang){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//做某些额外的事情，比如初始化之类，此处略&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; swith(lang){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;case&lt;/span&gt; Language.English:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; EnglishGreeting(name);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;break&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;case&lt;/span&gt; Language.Chinese:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ChineseGreeting(name);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;break&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;OK，尽管这样解决了问题，但我不说大家也很容易想到，这个解决方案的可扩展性很差，如果日后我们需要再添加韩文版、日文版，就不得不反复修改枚举和GreetPeople()方法，以适应新的需求。&lt;/p&gt;&#xD;
&lt;p&gt;在考虑新的解决方案之前，我们先看看 GreetPeople的方法签名：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; GreetPeople(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name, Language lang)&lt;/p&gt;&#xD;
&lt;p&gt;我们仅看 string name，在这里，string 是参数类型，name 是参数变量，当我们赋给name字符串&amp;#8220;jimmy&amp;#8221;时，它就代表&amp;#8220;jimmy&amp;#8221;这个值；当我们赋给它&amp;#8220;张子阳&amp;#8221;时，它又代表着&amp;#8220;张子阳&amp;#8221;这个值。然后，我们可以在方法体内对这个name进行其他操作。哎，这简直是废话么，刚学程序就知道了。&lt;/p&gt;&#xD;
&lt;p&gt;如果你再仔细想想，假如GreetPeople()方法可以接受一个参数变量，这个变量可以代表另一个方法，当我们给这个变量赋值 EnglishGreeting的时候，它代表着 EnglsihGreeting() 这个方法；当我们给它赋值ChineseGreeting 的时候，它又代表着ChineseGreeting()方法。我们将这个参数变量命名为 MakeGreeting，那么不是可以如同给name赋值时一样，在调用 GreetPeople()方法的时候，给这个MakeGreeting 参数也赋上值么(ChineseGreeting或者EnglsihGreeting等)？然后，我们在方法体内，也可以像使用别的参数一样使用MakeGreeting。但是，由于MakeGreeting代表着一个方法，它的使用方式应该和它被赋的方法(比如ChineseGreeting)是一样的，比如：&lt;/p&gt;&#xD;
&lt;p &gt;MakeGreeting(name);&lt;/p&gt;&#xD;
&lt;p&gt;好了，有了思路了，我们现在就来改改GreetPeople()方法，那么它应该是这个样子了：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; GreetPeople(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name, *** MakeGreeting){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MakeGreeting(name);&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;注意到 *** ，这个位置通常放置的应该是参数的类型，但到目前为止，我们仅仅是想到应该有个可以代表方法的参数，并按这个思路去改写GreetPeople方法，现在就出现了一个大问题：&lt;strong&gt;这个代表着方法的MakeGreeting参数应该是什么类型的？&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p &gt;&lt;strong&gt;NOTE：&lt;/strong&gt;这里已不再需要枚举了，因为在给MakeGreeting赋值的时候动态地决定使用哪个方法，是ChineseGreeting还是 EnglishGreeting，而在这个两个方法内部，已经对使用&amp;#8220;morning&amp;#8221;还是&amp;#8220;早上好&amp;#8221;作了区分。&lt;/p&gt;&#xD;
&lt;p&gt;聪明的你应该已经想到了，现在是委托该出场的时候了，但讲述委托之前，我们再看看MakeGreeting参数所能代表的 ChineseGreeting()和EnglishGreeting()方法的签名：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; EnglishGreeting(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name)&lt;br /&gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; ChineseGreeting(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name)&lt;/p&gt;&#xD;
&lt;p&gt;如同name可以接受String类型的&amp;#8220;true&amp;#8221;和&amp;#8220;1&amp;#8221;，但不能接受bool类型的true和int类型的1一样。&lt;strong&gt;MakeGreeting的 参数类型定义 应该能够确定 MakeGreeting可以代表的方法种类，再进一步讲，就是MakeGreeting可以代表的方法 的 参数类型和返回类型。&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;于是，委托出现了：&lt;strong&gt;它定义了MakeGreeting参数所能代表的方法的种类，也就是MakeGreeting参数的类型。&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p &gt;&lt;strong&gt;NOTE：&lt;/strong&gt;如果上面这句话比较绕口，我把它翻译成这样：string 定义了name参数所能代表的&lt;strong&gt;值的种类&lt;/strong&gt;，也就是name参数的类型。&lt;/p&gt;&#xD;
&lt;p&gt;本例中委托的定义：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;delegate&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; GreetingDelegate(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name);&lt;/p&gt;&#xD;
&lt;p&gt;可以与上面EnglishGreeting()方法的签名对比一下，除了加入了delegate关键字以外，其余的是不是完全一样？&lt;/p&gt;&#xD;
&lt;p&gt;现在，让我们再次改动GreetPeople()方法，如下所示：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; GreetPeople(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name, GreetingDelegate MakeGreeting){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MakeGreeting(name);&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;如你所见，委托GreetingDelegate出现的位置与 string相同，string是一个类型，那么GreetingDelegate应该也是一个类型，或者叫类(Class)。但是委托的声明方式和类却完全不同，这是怎么一回事？实际上，委托在编译的时候确实会编译成类。因为Delegate是一个类，所以在任何可以声明类的地方都可以声明委托。更多的内容将在下面讲述，现在，请看看这个范例的完整代码：&lt;/p&gt;&#xD;
&lt;p &gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Text;&lt;br /&gt;&lt;br /&gt;namespace Delegate {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //定义委托，它定义了可以代表的方法的类型&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;delegate&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; GreetingDelegate(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; class Program {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; private static void EnglishGreeting(string name) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Morning, " + name);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; private static void ChineseGreeting(string name) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("早上好, " + name);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //注意此方法，它接受一个GreetingDelegate类型的方法作为参数&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static void GreetPeople(string name, GreetingDelegate MakeGreeting) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MakeGreeting(name);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main(string[] args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GreetPeople("Jimmy Zhang", EnglishGreeting);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GreetPeople("张子阳", ChineseGreeting);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.ReadKey();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;输出如下：&lt;br /&gt;Morning, Jimmy Zhang&lt;br /&gt;早上好, 张子阳&lt;/p&gt;&#xD;
&lt;p&gt;我们现在对委托做一个总结：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;委托是一个类，它定义了方法的类型，使得可以将方法当作另一个方法的参数来进行传递，这种将方法动态地赋给参数的做法，可以避免在程序中大量使用If-Else(Switch)语句，同时使得程序具有更好的可扩展性。&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;将方法绑定到委托&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;看到这里，是不是有那么点如梦初醒的感觉？于是，你是不是在想：在上面的例子中，我不一定要直接在GreetPeople()方法中给 name参数赋值，我可以像这样使用变量：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;static&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; Main(&lt;span style="color: #00f"&gt;string&lt;/span&gt;[] args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;string&lt;/span&gt; name1, name2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; name1 = &lt;span style="color: #a31515"&gt;"Jimmy Zhang"&lt;/span&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; name2 = &lt;span style="color: #a31515"&gt;"张子阳"&lt;/span&gt;; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GreetPeople(name1, EnglishGreeting);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GreetPeople(name2, ChineseGreeting);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.ReadKey();&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;而既然委托GreetingDelegate 和 类型 string 的地位一样，都是定义了一种参数类型，那么，我是不是也可以这么使用委托？&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;static&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; Main(&lt;span style="color: #00f"&gt;string&lt;/span&gt;[] args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GreetingDelegate delegate1, delegate2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate1 = EnglishGreeting;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate2 = ChineseGreeting;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GreetPeople(&lt;span style="color: #a31515"&gt;"Jimmy Zhang"&lt;/span&gt;, delegate1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; GreetPeople(&lt;span style="color: #a31515"&gt;"张子阳"&lt;/span&gt;, delegate2);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.ReadKey();&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;如你所料，这样是没有问题的，程序一如预料的那样输出。这里，我想说的是委托不同于string的一个特性：可以将多个方法赋给同一个委托，或者叫将多个方法绑定到同一个委托，当调用这个委托的时候，将依次调用其所绑定的方法。在这个例子中，语法如下：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;static&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; Main(&lt;span style="color: #00f"&gt;string&lt;/span&gt;[] args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;GreetingDelegate&lt;/span&gt; delegate1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate1 = EnglishGreeting; &lt;span style="color: #008000"&gt;// 先给委托类型的变量赋值&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate1 += ChineseGreeting;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 给此委托变量再绑定一个方法&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 将先后调用 EnglishGreeting 与 ChineseGreeting 方法&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GreetPeople(&lt;span style="color: #a31515"&gt;"Jimmy Zhang"&lt;/span&gt;, delegate1);&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.ReadKey();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;输出为：&lt;br /&gt;Morning, Jimmy Zhang&lt;br /&gt;早上好, Jimmy Zhang&lt;/p&gt;&#xD;
&lt;p&gt;实际上，我们可以也可以绕过GreetPeople方法，通过委托来直接调用EnglishGreeting和ChineseGreeting：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;static&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; Main(&lt;span style="color: #00f"&gt;string&lt;/span&gt;[] args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;GreetingDelegate&lt;/span&gt; delegate1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate1 = EnglishGreeting; &lt;span style="color: #008000"&gt;// 先给委托类型的变量赋值&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate1 += ChineseGreeting;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 给此委托变量再绑定一个方法&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 将先后调用 EnglishGreeting 与 ChineseGreeting 方法&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate1 (&lt;span style="color: #a31515"&gt;"Jimmy Zhang"&lt;/span&gt;);&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.ReadKey();&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p &gt;&lt;strong&gt;NOTE：&lt;/strong&gt;这在本例中是没有问题的，但回头看下上面GreetPeople()的定义，在它之中可以做一些对于EnglshihGreeting和ChineseGreeting来说都需要进行的工作，为了简便我做了省略。&lt;/p&gt;&#xD;
&lt;p&gt;注意这里，第一次用的&amp;#8220;=&amp;#8221;，是赋值的语法；第二次，用的是&amp;#8220;+=&amp;#8221;，是绑定的语法。如果第一次就使用&amp;#8220;+=&amp;#8221;，将出现&amp;#8220;使用了未赋值的局部变量&amp;#8221;的编译错误。&lt;/p&gt;&#xD;
&lt;p&gt;我们也可以使用下面的代码来这样简化这一过程：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #2b91af"&gt;GreetingDelegate &lt;/span&gt;delegate1 = &lt;span style="color: #00f"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;GreetingDelegate&lt;/span&gt;(EnglishGreeting);&lt;br /&gt;delegate1 += ChineseGreeting;&amp;nbsp;&amp;nbsp; // 给此委托变量再绑定一个方法&lt;/p&gt;&#xD;
&lt;p&gt;看到这里，应该注意到，这段代码第一条语句与实例化一个类是何其的相似，你不禁想到：上面第一次绑定委托时不可以使用&amp;#8220;+=&amp;#8221;的编译错误，或许可以用这样的方法来避免：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #2b91af"&gt;GreetingDelegate &lt;/span&gt;delegate1 = &lt;span style="color: #00f"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;GreetingDelegate&lt;/span&gt;();&lt;br /&gt;delegate1 += EnglishGreeting;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 这次用的是 &amp;#8220;+=&amp;#8221;，绑定语法。&lt;br /&gt;&lt;/span&gt;delegate1 += ChineseGreeting;&amp;nbsp;&amp;nbsp; // 给此委托变量再绑定一个方法&lt;/p&gt;&#xD;
&lt;p&gt;但实际上，这样会出现编译错误： &amp;#8220;GreetingDelegate&amp;#8221;方法没有采用&amp;#8220;&lt;st1&gt;0&amp;#8221;&lt;/st1&gt;个参数的重载。尽管这样的结果让我们觉得有点沮丧，但是编译的提示：&amp;#8220;没有0个参数的重载&amp;#8221;再次让我们联想到了类的构造函数。我知道你一定按捺不住想探个究竟，但再此之前，我们需要先把基础知识和应用介绍完。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;既然给委托可以绑定一个方法，那么也应该有办法取消对方法的绑定，很容易想到，这个语法是&amp;#8220;-=&amp;#8221;：&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;static&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; Main(&lt;span style="color: #00f"&gt;string&lt;/span&gt;[] args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;GreetingDelegate &lt;/span&gt;delegate1 = &lt;span style="color: #00f"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;GreetingDelegate&lt;/span&gt;(EnglishGreeting);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate1 += ChineseGreeting;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 给此委托变量再绑定一个方法&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 将先后调用 EnglishGreeting 与 ChineseGreeting 方法&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GreetPeople(&lt;span style="color: #a31515"&gt;"Jimmy Zhang"&lt;/span&gt;, delegate1);&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate1 -= EnglishGreeting; &lt;span style="color: #008000"&gt;//取消对EnglishGreeting方法的绑定&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 将仅调用 ChineseGreeting &lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GreetPeople(&lt;span style="color: #a31515"&gt;"张子阳"&lt;/span&gt;, delegate1); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.ReadKey();&lt;br /&gt;}&lt;br /&gt;输出为：&lt;br /&gt;Morning, Jimmy Zhang&lt;br /&gt;早上好, Jimmy Zhang&lt;br /&gt;早上好, 张子阳&lt;/p&gt;&#xD;
&lt;p&gt;让我们再次对委托作个总结：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;使用委托可以将多个方法绑定到同一个委托变量，当调用此变量时(这里用&amp;#8220;调用&amp;#8221;这个词，是因为此变量代表一个方法)，可以依次调用所有绑定的方法。&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;事件的由来&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;我们继续思考上面的程序：上面的三个方法都定义在Programe类中，这样做是为了理解的方便，实际应用中，通常都是 GreetPeople 在一个类中，ChineseGreeting和 EnglishGreeting 在另外的类中。现在你已经对委托有了初步了解，是时候对上面的例子做个改进了。假设我们将GreetingPeople()放在一个叫GreetingManager的类中，那么新程序应该是这个样子的：&lt;/p&gt;&#xD;
&lt;p &gt;namespace Delegate {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //定义委托，它定义了可以代表的方法的类型&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;delegate&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; GreetingDelegate(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //新建的GreetingManager类&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class GreetingManager{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void GreetPeople(string name, GreetingDelegate MakeGreeting) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MakeGreeting(name);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; class Program {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static void EnglishGreeting(string name) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Morning, " + name);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static void ChineseGreeting(string name) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("早上好, " + name);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main(string[] args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ... ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;这个时候，如果要实现前面演示的输出效果，Main方法我想应该是这样的：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;static&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; Main(&lt;span style="color: #00f"&gt;string&lt;/span&gt;[] args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;GreetingManager&lt;/span&gt; gm = &lt;span style="color: #00f"&gt;new&lt;/span&gt; &amp;nbsp;GreetingManager();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gm.GreetPeople(&lt;span style="color: #a31515"&gt;"Jimmy Zhang"&lt;/span&gt;, EnglishGreeting);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gm.GreetPeople(&lt;span style="color: #a31515"&gt;"张子阳"&lt;/span&gt;, ChineseGreeting);&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;我们运行这段代码，嗯，没有任何问题。程序一如预料地那样输出了：&lt;/p&gt;&#xD;
&lt;p &gt;Morning, Jimmy Zhang&lt;/p&gt;&#xD;
&lt;p &gt;早上好, 张子阳&lt;/p&gt;&#xD;
&lt;p&gt;现在，假设我们需要使用上一节学到的知识，将多个方法绑定到同一个委托变量，该如何做呢？让我们再次改写代码：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;static&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; &lt;st1&gt;Main&lt;/st1&gt;(&lt;span style="color: #00f"&gt;string&lt;/span&gt;[] args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;GreetingManager&lt;/span&gt; gm = &lt;span style="color: #00f"&gt;new&lt;/span&gt;&amp;nbsp; GreetingManager();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;GreetingDelegate&lt;/span&gt; delegate1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate1 = EnglishGreeting;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate1 += ChineseGreeting;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gm.GreetPeople(&lt;span style="color: #a31515"&gt;"Jimmy Zhang"&lt;/span&gt;, delegate1);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;输出：&lt;br /&gt;Morning, Jimmy Zhang&lt;br /&gt;早上好, Jimmy Zhang&lt;/p&gt;&#xD;
&lt;p&gt;到了这里，我们不禁想到：面向对象设计，讲究的是对象的封装，既然可以声明委托类型的变量(在上例中是delegate1)，我们何不将这个变量封装到 GreetManager类中？在这个类的客户端中使用不是更方便么？于是，我们改写GreetManager类，像这样：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;GreetingManager&lt;/span&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//在GreetingManager类的内部声明delegate1变量&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af"&gt;GreetingDelegate&lt;/span&gt; delegate1;&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; GreetPeople(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name, GreetingDelegate MakeGreeting) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MakeGreeting(name);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;现在，我们可以这样使用这个委托变量：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;static&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; Main(&lt;span style="color: #00f"&gt;string&lt;/span&gt;[] args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;GreetingManager&lt;/span&gt; gm = &lt;span style="color: #00f"&gt;new&lt;/span&gt;&amp;nbsp; GreetingManager();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gm.delegate1 = EnglishGreeting;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gm.delegate1 += ChineseGreeting;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gm.GreetPeople(&lt;span style="color: #a31515"&gt;"Jimmy Zhang"&lt;/span&gt;, gm.delegate1);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;输出为：&lt;br /&gt;Morning, Jimmy Zhang&lt;br /&gt;早上好, Jimmy Zhang&lt;/p&gt;&#xD;
&lt;p&gt;尽管这样做没有任何问题，但我们发现这条语句很奇怪。在调用gm.GreetPeople方法的时候，再次传递了gm的delegate1字段：&lt;/p&gt;&#xD;
&lt;p &gt;gm.GreetPeople(&lt;span style="color: #a31515"&gt;"Jimmy Zhang"&lt;/span&gt;, gm.delegate1);&lt;/p&gt;&#xD;
&lt;p&gt;既然如此，我们何不修改 GreetingManager 类成这样：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;GreetingManager&lt;/span&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//在GreetingManager类的内部声明delegate1变量&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af"&gt;GreetingDelegate&lt;/span&gt; delegate1;&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; GreetPeople(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;if&lt;/span&gt;(delegate1!=&lt;span style="color: #00f"&gt;null&lt;/span&gt;){&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//如果有方法注册委托变量&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate1(name);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//通过委托调用方法&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;在客户端，调用看上去更简洁一些：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;static&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; Main(&lt;span style="color: #00f"&gt;string&lt;/span&gt;[] args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;GreetingManager&lt;/span&gt; gm = &lt;span style="color: #00f"&gt;new&lt;/span&gt;&amp;nbsp; GreetingManager();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gm.delegate1 = EnglishGreeting;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gm.delegate1 += ChineseGreeting;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gm.GreetPeople(&lt;span style="color: #a31515"&gt;"Jimmy Zhang"&lt;/span&gt;);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//注意，这次不需要再传递 delegate1变量&lt;br /&gt;&lt;/span&gt;}&lt;br /&gt;&lt;br /&gt;输出为：&lt;br /&gt;Morning, Jimmy Zhang&lt;br /&gt;早上好, Jimmy Zhang&lt;/p&gt;&#xD;
&lt;p&gt;尽管这样达到了我们要的效果，但是还是存在着问题：&lt;/p&gt;&#xD;
&lt;p&gt;在这里，delegate1和我们平时用的string类型的变量没有什么分别，而我们知道，并不是所有的字段都应该声明成public，合适的做法是应该public的时候public，应该private的时候private。&lt;/p&gt;&#xD;
&lt;p&gt;我们先看看如果把 delegate1 声明为 private会怎样？结果就是：&lt;strong&gt;这简直就是在搞笑。因为声明委托的目的就是为了把它暴露在类的客户端进行方法的注册，你把它声明为private了，客户端对它根本就不可见，那它还有什么用？&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;再看看把delegate1 声明为 public 会怎样？结果就是：&lt;strong&gt;在客户端可以对它进行随意的赋值等操作，严重破坏对象的封装性。&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;最后，第一个方法注册用&amp;#8220;=&amp;#8221;，是赋值语法，因为要进行实例化，第二个方法注册则用的是&amp;#8220;+=&amp;#8221;。但是，不&lt;strong&gt;管是赋值还是注册，都是将方法绑定到委托上，除了调用时先后顺序不同，再没有任何的分别，这样不是让人觉得很别扭么？&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;现在我们想想，如果delegate1不是一个委托类型，而是一个string类型，你会怎么做？&lt;strong&gt;答案是使用属性对字段进行封装。&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;于是，Event出场了，它封装了委托类型的变量，使得：&lt;strong&gt;在类的内部，不管你声明它是public还是protected，它总是private的。在类的外部，注册&amp;#8220;+=&amp;#8221;和注销&amp;#8220;-=&amp;#8221;的访问限定符与你在声明事件时使用的访问符相同。&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;我们改写GreetingManager类，它变成了这个样子：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;GreetingManager&lt;/span&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//这一次我们在这里声明一个事件&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;event&lt;/span&gt; &lt;span style="color: #2b91af"&gt;GreetingDelegate&lt;/span&gt; MakeGreet;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; GreetPeople(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; MakeGreet(name);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;很容易注意到：MakeGreet 事件的声明与之前委托变量delegate1的声明唯一的区别是多了一个event关键字。看到这里，在结合上面的讲解，你应该明白到：&lt;strong&gt;事件其实没什么不好理解的，声明一个事件不过类似于声明一个进行了封装的委托类型的变量而已。&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;为了证明上面的推论，如果我们像下面这样改写Main方法：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;static&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; Main(&lt;span style="color: #00f"&gt;string&lt;/span&gt;[] args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;GreetingManager&lt;/span&gt; gm = &lt;span style="color: #00f"&gt;new&lt;/span&gt;&amp;nbsp; GreetingManager();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gm.MakeGreet = EnglishGreeting;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 编译错误1&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gm.MakeGreet += ChineseGreeting;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; gm.GreetPeople(&lt;span style="color: #a31515"&gt;"Jimmy Zhang"&lt;/span&gt;);&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;会得到编译错误：事件&amp;#8220;Delegate.GreetingManager.MakeGreet&amp;#8221;只能出现在 += 或 -= 的左边(从类型&amp;#8220;Delegate.GreetingManager&amp;#8221;中使用时除外)。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;事件和委托的编译代码&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这时候，我们注释掉编译错误的行，然后重新进行编译，再借助Reflactor来对 event的声明语句做一探究，看看为什么会发生这样的错误：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;event&lt;/span&gt; &lt;span style="color: #2b91af"&gt;GreetingDelegate&lt;/span&gt; MakeGreet;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img alt=" " src="http://www.tracefact.net/graph/delegate/01.gif" width="433" height="101" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;可以看到，实际上尽管我们在GreetingManager里将 MakeGreet 声明为public，但是，实际上MakeGreet会被编译成 私有字段，难怪会发生上面的编译错误了，因为它根本就不允许在GreetingManager类的外面以赋值的方式访问，从而验证了我们上面所做的推论。&lt;/p&gt;&#xD;
&lt;p&gt;我们再进一步看下MakeGreet所产生的代码：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af"&gt;GreetingDelegate&lt;/span&gt; MakeGreet; &lt;span style="color: #008000"&gt;//对事件的声明 实际是 声明一个私有的委托变量&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&lt;br /&gt;[MethodImpl(MethodImplOptions.Synchronized)]&lt;br /&gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; add_MakeGreet(GreetingDelegate value){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;this&lt;/span&gt;.MakeGreet = (GreetingDelegate) Delegate.Combine(&lt;span style="color: #00f"&gt;this&lt;/span&gt;.MakeGreet, value);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[MethodImpl(MethodImplOptions.Synchronized)]&lt;br /&gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; remove_MakeGreet(GreetingDelegate value){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;this&lt;/span&gt;.MakeGreet = (GreetingDelegate) Delegate.Remove(&lt;span style="color: #00f"&gt;this&lt;/span&gt;.MakeGreet, value);&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;现在已经很明确了：&lt;strong&gt;MakeGreet事件确实是一个GreetingDelegate类型的委托，只不过不管是不是声明为public，它总是被声明为private。另外，它还有两个方法，分别是add_MakeGreet和remove_MakeGreet，这两个方法分别用于注册委托类型的方法和取消注册。&lt;/strong&gt;实际上也就是： &amp;#8220;+= &amp;#8221;对应 add_MakeGreet，&amp;#8220;-=&amp;#8221;对应remove_MakeGreet。而这两个方法的访问限制取决于声明事件时的访问限制符。&lt;/p&gt;&#xD;
&lt;p&gt;在add_MakeGreet()方法内部，实际上调用了System.Delegate的Combine()静态方法，这个方法用于将当前的变量添加到委托链表中。我们前面提到过两次，说委托实际上是一个类，在我们定义委托的时候：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;delegate&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; GreetingDelegate(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name);&lt;/p&gt;&#xD;
&lt;p&gt;当编译器遇到这段代码的时候，会生成下面这样一个完整的类：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;sealed&lt;/span&gt; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;GreetingDelegate&lt;/span&gt;:System.MulticastDelegate{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; GreetingDelegate(&lt;span style="color: #00f"&gt;object&lt;/span&gt; @&lt;span style="color: #00f"&gt;object&lt;/span&gt;, IntPtr method);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;virtual&lt;/span&gt; IAsyncResult BeginInvoke(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name, AsyncCallback callback, &lt;span style="color: #00f"&gt;object&lt;/span&gt; @&lt;span style="color: #00f"&gt;object&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;virtual&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; EndInvoke(IAsyncResult result);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;virtual&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; Invoke(&lt;span style="color: #00f"&gt;string&lt;/span&gt; name);&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;p&gt;&lt;img alt=" " src="http://www.tracefact.net/graph/delegate/02.gif" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;关于这个类的更深入内容，可以参阅《CLR Via C#》等相关书籍，这里就不再讨论了。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;委托、事件与Observer设计模式&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;范例说明&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;上面的例子已不足以再进行下面的讲解了，我们来看一个新的范例，因为之前已经介绍了很多的内容，所以本节的进度会稍微快一些：&lt;/p&gt;&#xD;
&lt;p&gt;假设我们有个高档的热水器，我们给它通上电，当水温超过95度的时候：1、扬声器会开始发出语音，告诉你水的温度；2、液晶屏也会改变水温的显示，来提示水已经快烧开了。&lt;/p&gt;&#xD;
&lt;p&gt;现在我们需要写个程序来模拟这个烧水的过程，我们将定义一个类来代表热水器，我们管它叫：Heater，它有代表水温的字段，叫做temperature；当然，还有必不可少的给水加热方法BoilWater()，一个发出语音警报的方法MakeAlert()，一个显示水温的方法，ShowMsg()。&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #00f"&gt;namespace&lt;/span&gt; Delegate {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Heater&lt;/span&gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af"&gt;&lt;span style="color: #00f"&gt;int&lt;/span&gt;&lt;/span&gt; temperature; &lt;span style="color: #008000"&gt;// 水温&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 烧水&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; BoilWater() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;for&lt;/span&gt; (&lt;span style="color: #00f"&gt;int&lt;/span&gt; i = 0; i &amp;lt;= 100; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; temperature = i;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;if&lt;/span&gt; (temperature &amp;gt; 95) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; MakeAlert(temperature);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ShowMsg(temperature);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 发出语音警报&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;private&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; MakeAlert(&lt;span style="color: #00f"&gt;int&lt;/span&gt; param) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;"Alarm：嘀嘀嘀，水已经 {0} 度了："&lt;/span&gt; , param);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 显示水温&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;private&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; ShowMsg(&lt;span style="color: #00f"&gt;int&lt;/span&gt; param) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;"Display：水快开了，当前温度：{0}度。"&lt;/span&gt; , param);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Program&lt;/span&gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;static&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; &lt;st1&gt;Main&lt;/st1&gt;() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Heater &lt;/span&gt;ht = &lt;span style="color: #00f"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Heater&lt;/span&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ht.BoilWater();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;Observer设计模式简介&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;上面的例子显然能完成我们之前描述的工作，但是却并不够好。现在假设热水器由三部分组成：热水器、警报器、显示器，它们来自于不同厂商并进行了组装。那么，应该是&lt;strong&gt;热水器&lt;/strong&gt;仅仅负责烧水，它不能发出警报也不能显示水温；在水烧开时由&lt;strong&gt;警报器&lt;/strong&gt;发出警报、&lt;strong&gt;显示器&lt;/strong&gt;显示提示和水温。&lt;/p&gt;&#xD;
&lt;p&gt;这时候，上面的例子就应该变成这个样子：&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #008000"&gt;// 热水器&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Heater&lt;/span&gt; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af"&gt;&lt;span style="color: #00f"&gt;int&lt;/span&gt;&lt;/span&gt; temperature;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 烧水&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;private&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; BoilWater() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;for&lt;/span&gt; (&lt;span style="color: #00f"&gt;int&lt;/span&gt; i = 0; i &amp;lt;= 100; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; temperature = i;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// 警报器&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Alarm&lt;/span&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;private&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; MakeAlert(&lt;span style="color: #00f"&gt;int&lt;/span&gt; param) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;"Alarm：嘀嘀嘀，水已经 {0} 度了："&lt;/span&gt; , param);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #008000"&gt;// 显示器&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Display&lt;/span&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;private&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; ShowMsg(&lt;span style="color: #00f"&gt;int&lt;/span&gt; param) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;"Display：水已烧开，当前温度：{0}度。"&lt;/span&gt; , param);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;这里就出现了一个问题：如何在水烧开的时候通知报警器和显示器？在继续进行之前，我们先了解一下Observer设计模式，Observer设计模式中主要包括如下两类对象：&lt;/p&gt;&#xD;
&lt;ol&gt;&lt;li&gt;Subject：监视对象，它往往包含着其他对象所感兴趣的内容。在本范例中，热水器就是一个监视对象，它包含的其他对象所感兴趣的内容，就是temprature字段，当这个字段的值快到100时，会不断把数据发给监视它的对象。&lt;/li&gt;&lt;li&gt;Observer：监视者，它监视Subject，当Subject中的某件事发生的时候，会告知Observer，而Observer则会采取相应的行动。在本范例中，Observer有警报器和显示器，它们采取的行动分别是发出警报和显示水温。 &lt;/li&gt;&lt;/ol&gt;&#xD;
&lt;p&gt;在本例中，事情发生的顺序应该是这样的：&lt;/p&gt;&#xD;
&lt;ol&gt;&lt;li&gt;警报器和显示器告诉热水器，它对它的温度比较感兴趣(注册)。&lt;/li&gt;&lt;li&gt;热水器知道后保留对警报器和显示器的引用。&lt;/li&gt;&lt;li&gt;热水器进行烧水这一动作，当水温超过95度时，通过对警报器和显示器的引用，自动调用警报器的MakeAlert()方法、显示器的ShowMsg()方法。 &lt;/li&gt;&lt;/ol&gt;&#xD;
&lt;p&gt;类似这样的例子是很多的，GOF对它进行了抽象，称为Observer设计模式：&lt;strong&gt;Observer设计模式是为了定义对象间的一种一对多的依赖关系，以便于当一个对象的状态改变时，其他依赖于它的对象会被自动告知并更新。Observer模式是一种松耦合的设计模式。&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;实现范例的Observer设计模式&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;我们之前已经对委托和事件介绍很多了，现在写代码应该很容易了，现在在这里直接给出代码，并在注释中加以说明。&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #2b91af"&gt;&lt;span style="color: #00f"&gt;using&lt;/span&gt;&lt;/span&gt; System;&lt;br /&gt;&lt;span style="color: #00f"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;&lt;span style="color: #00f"&gt;using&lt;/span&gt; System.Text;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #00f"&gt;namespace&lt;/span&gt; Delegate {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 热水器&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Heater&lt;/span&gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af"&gt;&lt;span style="color: #00f"&gt;int&lt;/span&gt;&lt;/span&gt; temperature;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;delegate&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; BoilHandler(&lt;span style="color: #00f"&gt;int&lt;/span&gt; param);&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//声明委托&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;event&lt;/span&gt; &lt;span style="color: #2b91af"&gt;BoilHandler&lt;/span&gt; BoilEvent;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//声明事件&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 烧水&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; BoilWater() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;for&lt;/span&gt; (&lt;span style="color: #00f"&gt;int&lt;/span&gt; i = 0; i &amp;lt;= 100; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; temperature = i;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;if&lt;/span&gt; (temperature &amp;gt; 95) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;if&lt;/span&gt; (BoilEvent != &lt;span style="color: #00f"&gt;null&lt;/span&gt;) { &lt;span style="color: #008000"&gt;//如果有对象注册&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BoilEvent(temperature);&amp;nbsp; &lt;span style="color: #008000"&gt;//调用所有注册对象的方法&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 警报器&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Alarm&lt;/span&gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; MakeAlert(&lt;span style="color: #00f"&gt;int&lt;/span&gt; param) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;"Alarm：嘀嘀嘀，水已经 {0} 度了："&lt;/span&gt;, param);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 显示器&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Display&lt;/span&gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;static&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; ShowMsg(&lt;span style="color: #00f"&gt;int&lt;/span&gt; param) { &lt;span style="color: #008000"&gt;//静态方法&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;"Display：水快烧开了，当前温度：{0}度。"&lt;/span&gt;, param);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Program&lt;/span&gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;static&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; &lt;st1&gt;Main&lt;/st1&gt;() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Heater &lt;/span&gt;heater = &lt;span style="color: #00f"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Heater&lt;/span&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Alarm &lt;/span&gt;alarm = &lt;span style="color: #00f"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Alarm&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; heater.BoilEvent += alarm.MakeAlert;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//注册方法&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; heater.BoilEvent += (&lt;span style="color: #00f"&gt;new&lt;/span&gt; Alarm()).MakeAlert;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//给匿名对象注册方法&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; heater.BoilEvent += Display.ShowMsg;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//注册静态方法&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; heater.BoilWater();&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//烧水，会自动调用注册过对象的方法&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;输出为：&lt;br /&gt;Alarm：嘀嘀嘀，水已经 96 度了：&lt;br /&gt;Alarm：嘀嘀嘀，水已经 96 度了：&lt;br /&gt;Display：水快烧开了，当前温度：96度。&lt;br /&gt;// 省略...&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;.Net Framework中的委托与事件&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;尽管上面的范例很好地完成了我们想要完成的工作，但是我们不仅疑惑：为什么.Net Framework 中的事件模型和上面的不同？为什么有很多的EventArgs参数？&lt;/p&gt;&#xD;
&lt;p&gt;在回答上面的问题之前，我们先搞懂 .Net Framework的编码规范：&lt;/p&gt;&#xD;
&lt;ul&gt;&lt;li&gt;委托类型的名称都应该以EventHandler结束。&lt;/li&gt;&lt;li&gt;委托的原型定义：有一个void返回值，并接受两个输入参数：一个Object 类型，一个 EventArgs类型(或继承自EventArgs)。&lt;/li&gt;&lt;li&gt;事件的命名为 委托去掉 EventHandler之后剩余的部分。&lt;/li&gt;&lt;li&gt;继承自EventArgs的类型应该以EventArgs结尾。 &lt;/li&gt;&lt;/ul&gt;&#xD;
&lt;p&gt;再做一下说明：&lt;/p&gt;&#xD;
&lt;ol&gt;&lt;li&gt;委托声明原型中的Object类型的参数代表了Subject，也就是监视对象，在本例中是 Heater(热水器)。回调函数(比如Alarm的MakeAlert)可以通过它访问触发事件的对象(Heater)。&lt;/li&gt;&lt;li&gt;EventArgs 对象包含了Observer所感兴趣的数据，在本例中是temperature。 &lt;/li&gt;&lt;/ol&gt;&#xD;
&lt;p&gt;&lt;strong&gt;上面这些其实不仅仅是为了编码规范而已，这样也使得程序有更大的灵活性。&lt;/strong&gt;比如说，如果我们不光想获得热水器的温度，还想在Observer端(警报器或者显示器)方法中获得它的生产日期、型号、价格，那么委托和方法的声明都会变得很麻烦，而如果我们将热水器的引用传给警报器的方法，就可以在方法中直接访问热水器了。&lt;/p&gt;&#xD;
&lt;p&gt;现在我们改写之前的范例，让它符合 .Net Framework 的规范：&lt;/p&gt;&#xD;
&lt;p &gt;&lt;span style="color: #2b91af"&gt;&lt;span style="color: #00f"&gt;using&lt;/span&gt;&lt;/span&gt; System;&lt;br /&gt;&lt;span style="color: #00f"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;&lt;span style="color: #00f"&gt;using&lt;/span&gt; System.Text;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #00f"&gt;namespace&lt;/span&gt; Delegate {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 热水器&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Heater&lt;/span&gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af"&gt;&lt;span style="color: #00f"&gt;int&lt;/span&gt;&lt;/span&gt; temperature;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af"&gt;&lt;span style="color: #00f"&gt;string&lt;/span&gt;&lt;/span&gt; type = &lt;span style="color: #a31515"&gt;"RealFire 001"&lt;/span&gt;;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 添加型号作为演示&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af"&gt;&lt;span style="color: #00f"&gt;string&lt;/span&gt;&lt;/span&gt; area = &lt;span style="color: #a31515"&gt;"China Xian"&lt;/span&gt;;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 添加产地作为演示&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//声明委托&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;delegate&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; BoiledEventHandler(Object sender, BoiledEventArgs e);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;event&lt;/span&gt; &lt;span style="color: #2b91af"&gt;BoiledEventHandler&lt;/span&gt; Boiled; &lt;span style="color: #008000"&gt;//声明事件&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 定义BoiledEventArgs类，传递给Observer所感兴趣的信息&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;BoiledEventArgs&lt;/span&gt; : &lt;span style="color: #2b91af"&gt;EventArgs&lt;/span&gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;readonly&lt;/span&gt; &lt;span style="color: #2b91af"&gt;&lt;span style="color: #00f"&gt;int&lt;/span&gt;&lt;/span&gt; temperature;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; BoiledEventArgs(&lt;span style="color: #00f"&gt;int&lt;/span&gt; temperature) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;this&lt;/span&gt;.temperature = temperature;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 可以供继承自 Heater 的类重写，以便继承类拒绝其他对象对它的监视&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;protected&lt;/span&gt; &lt;span style="color: #00f"&gt;virtual&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; OnBoiled(BoiledEventArgs e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;if&lt;/span&gt; (Boiled != &lt;span style="color: #00f"&gt;null&lt;/span&gt;) { &lt;span style="color: #008000"&gt;// 如果有对象注册&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Boiled(&lt;span style="color: #00f"&gt;this&lt;/span&gt;, e);&amp;nbsp; &lt;span style="color: #008000"&gt;// 调用所有注册对象的方法&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 烧水。&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; BoilWater() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;for&lt;/span&gt; (&lt;span style="color: #00f"&gt;int&lt;/span&gt; i = 0; i &amp;lt;= 100; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; temperature = i;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;if&lt;/span&gt; (temperature &amp;gt; 95) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//建立BoiledEventArgs 对象。&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BoiledEventArgs e = &lt;span style="color: #00f"&gt;new&lt;/span&gt; BoiledEventArgs(temperature);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OnBoiled(e);&amp;nbsp; &lt;span style="color: #008000"&gt;// 调用 OnBolied方法&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 警报器&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Alarm&lt;/span&gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; MakeAlert(Object sender, Heater.BoiledEventArgs e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Heater&lt;/span&gt; heater = (Heater)sender;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//这里是不是很熟悉呢？&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//访问 sender 中的公共字段&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;"Alarm：{0} - {1}: "&lt;/span&gt;, heater.area, heater.type);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;"Alarm: 嘀嘀嘀，水已经 {0} 度了："&lt;/span&gt;, e.temperature);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;// 显示器&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Display&lt;/span&gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;public&lt;/span&gt; &lt;span style="color: #00f"&gt;static&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; ShowMsg(Object sender, Heater.BoiledEventArgs e) {&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//静态方法&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Heater&lt;/span&gt; heater = (Heater)sender;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;"Display：{0} - {1}: "&lt;/span&gt;, heater.area, heater.type);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: #a31515"&gt;"Display：水快烧开了，当前温度：{0}度。"&lt;/span&gt;, e.temperature);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Console&lt;/span&gt;.WriteLine();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Program&lt;/span&gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #00f"&gt;static&lt;/span&gt; &lt;span style="color: #00f"&gt;void&lt;/span&gt; Main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Heater &lt;/span&gt;heater = &lt;span style="color: #00f"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Heater&lt;/span&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af"&gt;Alarm &lt;/span&gt;alarm = &lt;span style="color: #00f"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af"&gt;Alarm&lt;/span&gt;();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; heater.Boiled += alarm.MakeAlert;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//注册方法&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; heater.Boiled += (&lt;span style="color: #00f"&gt;new&lt;/span&gt; Alarm()).MakeAlert;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//给匿名对象注册方法&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; heater.Boiled += &lt;span style="color: #00f"&gt;new&lt;/span&gt; Heater.BoiledEventHandler(alarm.MakeAlert);&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//也可以这么注册&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; heater.Boiled += Display.ShowMsg;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//注册静态方法&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; heater.BoilWater();&amp;nbsp;&amp;nbsp; &lt;span style="color: #008000"&gt;//烧水，会自动调用注册过对象的方法&lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;输出为：&lt;br /&gt;Alarm：China Xian - RealFire 001:&lt;br /&gt;Alarm: 嘀嘀嘀，水已经 96 度了：&lt;br /&gt;Alarm：China Xian - RealFire 001:&lt;br /&gt;Alarm: 嘀嘀嘀，水已经 96 度了：&lt;br /&gt;Alarm：China Xian - RealFire 001:&lt;br /&gt;Alarm: 嘀嘀嘀，水已经 96 度了：&lt;br /&gt;Display：China Xian - RealFire 001:&lt;br /&gt;Display：水快烧开了，当前温度：96度。&lt;br /&gt;&lt;span style="color: #008000"&gt;// 省略 &lt;/span&gt;...&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;在本文中我首先通过一个GreetingPeople的小程序向大家介绍了委托的概念、委托用来做什么，随后又引出了事件，接着对委托与事件所产生的中间代码做了粗略的讲述。&lt;/p&gt;&#xD;
&lt;p&gt;在第二个稍微复杂点的热水器的范例中，我向大家简要介绍了 Observer设计模式，并通过实现这个范例完成了该模式，随后讲述了.Net Framework中委托、事件的实现方式。&lt;/p&gt;&#xD;
&lt;p&gt;希望这篇文章能给你带来帮助。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/aspnetcsharp/aggbug/1750630.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aspnetcsharp/articles/1750630.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aspnetcsharp/articles/1717356.html</id><title type="text">jQuery / 最流行八款Js框架介绍及比较</title><summary type="text">目前来看，JS框架以及一些开发包和库类有如下几个，Dojo 、Scriptaculous 、Prototype 、yui-ext 、Jquery 、Mochikit、mootools 、moo.fxDojo （JS library and UI component ）：Dojo是目前最为强大的j s框架，它在自己的Wiki上给自己下了一个定义，dojo是一个用JavaScript编写的开源的DHT...</summary><published>2010-04-21T08:33:00Z</published><updated>2010-04-21T08:33:00Z</updated><author><name>Benguo</name><uri>http://www.cnblogs.com/aspnetcsharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aspnetcsharp/articles/1717356.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aspnetcsharp/articles/1717356.html"/><content type="html">&lt;p&gt;目前来看，JS框架以及一些开发包和库类有如下几个，Dojo 、Scriptaculous 、Prototype 、yui-ext 、Jquery 、Mochikit、mootools 、moo.fx&lt;br /&gt;Dojo （JS library and UI component ）：&lt;br /&gt;Dojo是目前最为强大的j s框架，它在自己的Wiki上给自己下了一个定义，dojo是一个用JavaScript编写的开源的DHTML工具箱。dojo很想做一个&amp;#8220;大一统&amp;#8221;的 工具箱，不仅仅是浏览器层面的，野心还是很大的。Dojo包括ajax, browser, event, widget等跨浏览器API，包括了JS本身的语言扩展，以及各个方面的工具类库，和比较完善的UI组件库，也被广泛 应用在很多项目中，他的UI组件的特点是通过给html标签增加tag的方式进行扩展，而不是通过写JS来生成，dojo的API模仿Java类库的组织 方式。 用dojo写Web OS可谓非常方便。dojo现在已经4.0了，dojo强大的地方在于界面和特效的封装，可以让开发者快速构建一些兼容标准的界面。&lt;/p&gt;&#xD;
&lt;p&gt;优点：库相当完善，发展时间也比较长，功能强大，据说利用dojo的io.bind()可以实现comet，看见其功能强大非一般，得到IBM和SUN的支持&lt;br /&gt;缺点：文件体积比较大，200多KB，初次下载相当慢，此外，dojo的类库使用显得不是那么易用，j s语法增强方面不如prototype。&lt;/p&gt;&#xD;
&lt;p&gt;Prototype （JS OO library）：&lt;br /&gt;是一个非常优雅的JS库，定义了JS的面向对象扩展，DOM操作API，事件等等，以prototype为核心，形成了一个外围的各种各样 的JS扩展库，是相当有前途的JS底层框架，值得推荐，感觉也是现实中应用最广的库类（RoR集成的AJAX JS库），之上还有 Scriptaculous 实现一些JS组件功能和效果。&lt;/p&gt;&#xD;
&lt;p&gt;优点：基本底层，易学易用，甚至是其他一些js特效开发包的底层，体积算是最小的了。&lt;br /&gt;缺点：如果说缺点，可能就是功能是他的弱项&lt;/p&gt;&#xD;
&lt;p&gt;Scriptaculous （JS UI component based on prototype）：&lt;br /&gt;Scriptaculous是基于prototype.js框架的JS效果。包含了6个js文件，不同的文件对应不同的js效果，所以说，如果底层用 prototype的话，做js效果用Scriptaculous那是再合适不过的了，连大名鼎鼎的digg都在用他，可见不一般&lt;br /&gt;优点：基于prototype是最大的优点，由于使用prototype的广泛性，无疑对用户书锦上添花，并且在《ajax in action》中就拿Scriptaculous来讲述js效果&lt;br /&gt;缺点：刚刚兴起，需要时间的磨练&lt;/p&gt;&#xD;
&lt;p&gt;yui-ext (JS UI component)：&lt;br /&gt;基于Yahoo UI的扩展包yui-ext是具有CS风格的Web用户界面组件 能实现复杂的Layout布局，界面效果可以和backbase媲美，而且使用纯javascript代码开发。真正的可编辑的表格Edit Grid，支持XML和Json数据类型，直接可以迁入grid。许多组件实现了对数据源的支持，例如动态的布局，可编辑的表格控件，动态加载的Tree 控件、动态拖拽效果等等。1.0 beta版开始同Jquery合作，推出基于jQuery的Ext 1.0，提供了更多有趣的功能。&lt;br /&gt;优点：结构化，类似于java的结构，清晰明了，底层用到了Jquery的一些函数，使整合使用有了选择，最重要的一点是界面太让让人震撼了。&lt;br /&gt;缺点：太过复杂，整个界面的构造过于复杂。&lt;/p&gt;&#xD;
&lt;p&gt;Jquery ：&lt;br /&gt;jQuery是一款同prototype一样优秀js开发库类，特别是对css和XPath的支持，使我们写js变得更加方便！如果你不是个js高手又想写出优 秀的js效果，jQuery可以帮你达到目的！并且简介的语法和高的效率一直是jQuery追求的目标，&lt;/p&gt;&#xD;
&lt;p&gt;优点：注重简介和高效，js效果有yui-ext的选择，因为yui-ext 重用了很多jQuery的函数&lt;br /&gt;缺点：据说太嫩，历史不悠久。&lt;/p&gt;&#xD;
&lt;p&gt;Mochikit ：&lt;br /&gt;MochiKit自称为一个轻量级的js框架。MochiKit 主要受到 Python 和 Python 标准库提供的很多便利之处的启发，另外还缓解了浏览器版本之间的不一致性。其中的 MochiKit.DOM 尤其方便，能够以比原始 JavaScript 更友好的方式处理 DOM 对象。MochiKit.DOM 大部分都是针对 XHTML 文档定制的，如果与 MochiKit 和 Ajax 结合在一起，使用 XHTML 包装的微格式尤其方便。Mochikit可以直接对字符串或者数字格式化输出，比较实用和方便。它还有自己的 js 代码解释器&lt;/p&gt;&#xD;
&lt;p&gt;优点：MochiKit.DOM这部分很实用，简介也是很突出的&lt;br /&gt;缺点：轻量级的缺点&lt;/p&gt;&#xD;
&lt;p&gt;mootools ：&lt;br /&gt;MooTools是一个简洁，模块化，面向对象的JavaScript框架。它能够帮助你更快，更简单地编写可扩展和兼容性强的JavaScript代码。Mootools跟prototypejs相类似，语法几乎一样。但它提供的功能要比prototypejs多，而且更强大。比如增加了动画特效、拖放操作等等。&lt;/p&gt;&#xD;
&lt;p&gt;优点：可以定制自己所需要的功能，可以说是prototypejs的增强版。&lt;br /&gt;缺点：不大不小，具体应用具体分析&lt;br /&gt;moo.fx ：&lt;br /&gt;moo.fx是一个超级轻量级的javascript特效库（7k）,能够与prototype.js或mootools框架一起使用。它非常快、易于使用、跨浏览器、符合标准，提供控制和修改任何HTML元素的CSS属性，包括颜色。它内置检查器能够防止用户通过多次或疯狂点击来破坏效果。moo.fx整体采用模块化设计，所以可以在它的基础上开发你需要的任何特效。&lt;/p&gt;&#xD;
&lt;p&gt;优点：小块头有大能耐&lt;br /&gt;缺点：这么小了，已经不错了&lt;/p&gt; &lt;img src="http://www.cnblogs.com/aspnetcsharp/aggbug/1717356.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aspnetcsharp/articles/1717356.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aspnetcsharp/articles/1717260.html</id><title type="text">全国哀悼日 网站穿灰装（CSS）</title><summary type="text">根据国务院文件，5.19-5.21为全国哀悼日，在此期间，全国和各驻外机构下半旗志哀，停止公共娱乐活动，外交部和我国驻外使领馆设立吊唁簿。5月19日14时28分起，全国人民默哀3分钟，届时汽车、火车、舰船鸣笛，防空警报鸣响。 中国站长站将整站换成素装。并建议中国所有站点更换为素装。 为方便站点哀悼，特提供素装代码，以表哀悼。</summary><published>2010-04-21T07:15:00Z</published><updated>2010-04-21T07:15:00Z</updated><author><name>Benguo</name><uri>http://www.cnblogs.com/aspnetcsharp/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aspnetcsharp/articles/1717260.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aspnetcsharp/articles/1717260.html"/><content type="html">根据国务院文件，5.19-5.21为全国哀悼日，在此期间，全国和各驻外机构下半旗志哀，停止公共娱乐活动，外交部和我国驻外使领馆设立吊唁簿。5月19日14时28分起，全国人民默哀3分钟，届时汽车、火车、舰船鸣笛，防空警报鸣响。 中国站长站将整站换成素装。并建议中国所有站点更换为素装。&#xD;
&lt;p&gt;为方便站点哀悼，特提供素装代码，以表哀悼。以下为全站CSS代码。&lt;/p&gt;&#xD;
&lt;table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"&gt;&#xD;
    &lt;tbody&gt;&#xD;
        &lt;tr&gt;&#xD;
            &lt;td style="word-wrap: break-word" bgcolor="#fdfddf"&gt;&lt;font style="background-color: #ffffff" color="#ff0000"&gt;&lt;/font&gt;&lt;br /&gt;&#xD;
            &lt;font style="background-color: #ffffff" color="#ff0000"&gt;html { filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1); }&lt;/font&gt;&lt;/td&gt;&#xD;
        &lt;/tr&gt;&#xD;
    &lt;/tbody&gt;&#xD;
&lt;/table&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;使用方法：这段代码可以变网页为黑白，将代码加到CSS最顶端就可以实现素装。建议全国站长动起来。为在地震中遇难的同胞哀悼。&lt;/p&gt;&#xD;
&lt;p&gt;如果网站没有使用CSS，可以在网页/模板的HTML代码&amp;lt;head&amp;gt;和&amp;lt;/head&amp;gt; 之间插入：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"&gt;&#xD;
    &lt;tbody&gt;&#xD;
        &lt;tr&gt;&#xD;
            &lt;td style="word-wrap: break-word" bgcolor="#fdfddf"&gt;&lt;font face="新宋体"&gt;&amp;lt;style&amp;gt;&lt;br /&gt;&#xD;
            html{filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);}&lt;br /&gt;&#xD;
            &amp;lt;/style&amp;gt;&lt;/font&gt;&lt;/td&gt;&#xD;
        &lt;/tr&gt;&#xD;
    &lt;/tbody&gt;&#xD;
&lt;/table&gt;&#xD;
&lt;/p&gt;&#xD;
&lt;p&gt;有一些站长的网站可能使用这个css 不能生效，是因为网站没有使用最新的网页标准协议 &lt;/p&gt;&#xD;
&lt;p&gt;&lt;table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"&gt;&#xD;
    &lt;tbody&gt;&#xD;
        &lt;tr&gt;&#xD;
            &lt;td style="word-wrap: break-word" bgcolor="#fdfddf"&gt;&lt;font face="新宋体"&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&#xD;
            &amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;&lt;/font&gt;&lt;br /&gt;&#xD;
            &lt;/td&gt;&#xD;
        &lt;/tr&gt;&#xD;
    &lt;/tbody&gt;&#xD;
&lt;/table&gt;&#xD;
&lt;/p&gt;&#xD;
&lt;p&gt;请将网页最头部的&amp;lt;html&amp;gt;替换为以上代码。&lt;br /&gt;&#xD;
&lt;br /&gt;&#xD;
有一些网站FLASH动画的颜色不能被CSS滤镜控制，可以在FLASH代码的&amp;lt;object &amp;#8230;&amp;gt;和&amp;lt;/object&amp;gt;之间插入： &lt;/p&gt;&#xD;
&lt;p&gt;&lt;table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"&gt;&#xD;
    &lt;tbody&gt;&#xD;
        &lt;tr&gt;&#xD;
            &lt;td style="word-wrap: break-word" bgcolor="#fdfddf"&gt;&lt;font face="新宋体"&gt;&amp;lt;param value="false" name="menu"/&amp;gt;&lt;br /&gt;&#xD;
            &amp;lt;param value="opaque" name="wmode"/&amp;gt;&lt;/font&gt;&lt;br /&gt;&#xD;
            &lt;/td&gt;&#xD;
        &lt;/tr&gt;&#xD;
    &lt;/tbody&gt;&#xD;
&lt;/table&gt;&#xD;
&lt;/p&gt;&#xD;
&lt;p&gt;最简单的把页面变成灰色的代码是在head 之间加&amp;lt;style type="text/css"&amp;gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"&gt;&#xD;
    &lt;tbody&gt;&#xD;
        &lt;tr&gt;&#xD;
            &lt;td style="word-wrap: break-word" bgcolor="#fdfddf"&gt;&lt;font face="新宋体"&gt;html {&lt;br /&gt;&#xD;
            FILTER: gray&lt;br /&gt;&#xD;
            }&lt;br /&gt;&#xD;
            &amp;lt;/style&amp;gt;&lt;/font&gt;&lt;/td&gt;&#xD;
        &lt;/tr&gt;&#xD;
    &lt;/tbody&gt;&#xD;
&lt;/table&gt;&#xD;
&lt;/p&gt;&#xD;
&lt;p&gt;还有一种最简单的把页面变成灰色的代码是在body之中加入style="filter:gray" &lt;/p&gt;&#xD;
&lt;p&gt;&lt;table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"&gt;&#xD;
    &lt;tbody&gt;&#xD;
        &lt;tr&gt;&#xD;
            &lt;td style="word-wrap: break-word" bgcolor="#fdfddf"&gt;&lt;font face="新宋体"&gt;&amp;lt;body style="filter:gray"&amp;gt;&lt;/font&gt;&lt;/td&gt;&#xD;
        &lt;/tr&gt;&#xD;
    &lt;/tbody&gt;&#xD;
&lt;/table&gt;&#xD;
&lt;/p&gt; &lt;img src="http://www.cnblogs.com/aspnetcsharp/aggbug/1717260.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aspnetcsharp/articles/1717260.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
