首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 分享我所理解的c#中的委托『原创』 [已结贴,结贴人:keyake863]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 11:05:39 楼主
      c#语言的一大特点就是 高聚合,低耦合。而委托也很明显的体现了这样的一个特征。委托的价值并不在于它能帮你解决什么难题,而在于它能帮助你优化你的程序。

            很多情况下不用委托我们也能完成工作,也许偶尔会觉得使用委托更加麻烦,但是正如前面所说委托能使代码更加的低耦合,更加具有可读性,更加容易根据需求的改变而改变,也更加的简少了代码量。

            既然有那么多优点我们当然要使用,如果你对委托的优点仍然有所怀疑,那么我们一起完成下面的例子。

            有一个运动员,他叫green,他每周要训练三天,周一,周二和周三。而他每天训练完成后都要做不同的事情,但是这些事情是有规律的,他周一要将训练的分数交给manager,周二不用交了,但是他要自己记录下这个分数,周三他不用交也不用记录,但是他要把他的分数给他的队友看。

            这样一个游戏规则,我们试着用代码来实现它,首先,我们不考虑委托。

          显然,这个过程需要运动员在每次完成训练后传递一些信息(参数)给某些方法(提交给manager的方法,记录的方法,传递给其他队友的方法)我们把这三个方法写在一个DoSomeThing类中,result是我们定义的一个string用来记录结果。

            public class DoSomeThing
            ...{
                public void GiveCodeToManager(object sender, CustomeEvetnArgs e)
                ...{
                    result +=sender.ToString()+ "已经将分数:" + e.Code.ToString() + "送给Manager";
                }
                public void RecodeCode(object sender, CustomeEvetnArgs e)
                ...{
                    result += sender.ToString() + "已经将分数:" + e.Code.ToString() + "记录";
                }
                public void GiveCodeToOthers(object sender, CustomeEvetnArgs e)
                ...{
                    result += sender.ToString() + "已经将分数:" + e.Code.ToString() + "给其他人";
                }
            }
    传递的参数中有一个CustomeEvetnArgs,这是我们自定义的传递信息类。这个类将包含传递的分数,如下

            public class CustomeEvetnArgs : EventArgs
            ...{
                private string _code;
                public string Code
                ...{
                    get ...{ return _code; }
                    set ...{ _code = value; }
                }
            }
    我们还要有一个player类,运动员类,这个类中要根据时间的不同来调用dosomething类中的方法,并传递参数

    public class player
            ...{
                private string _code;
                public string Code
                ...{
                    get ...{ return _code; }
                    set ...{ _code = value; }
                }

                private string _thedate;
                public string TheDate
                ...{
                    get ...{ return _thedate; }
                    set ...{ _thedate = value; }
                }

                public void OnComplete()
                ...{
                    CustomeEvetnArgs e = new CustomeEvetnArgs();
                    e.Code = this.Code;

                    DoSomeThing things = new DoSomeThing();
                    if (_thedate == "Mon")
                    ...{ things.GiveCodeToManager(this, e); }
                    if (_thedate == "Tues")
                    ...{ things.RecodeCode(this, e); }
                    if (_thedate == "Wed")
                    ...{ things.GiveCodeToOthers(this, e); }
                }
            }
    这样基本类型就完成了,我们现在来调用它们

                player green = new player();
                green.Code = "A+";
                green.TheDate = "Tues";
                green.OnComplete();
                Response.Write(result);
    嗨,我们实现了这个游戏。测试一下,确实没有问题,如果你是一个细心的人也许你会回过头来检查你的代码,是否会发现一些不尽人意的地方?你会发现运动员类中包含的东西太多了,比如日期并不是一个运动员的属性,运动员和日期有什么关系呢?而运动员的唯一事件就是完成训练,他不需要去管其他事情了,他训练完了太累了,还要去送分数和记录成绩?也许他应该有个助手去做这些事情,所以在运动员类中并不应该出现那些if,他们使代码的耦合度太高了,当一个运动员想要改变他的训练流程时,他不得不改变player类。于是,委托出场了。

    定义一个委托,使用delegate关键字,后面跟上他的参数,这个委托是要委托他去处理dosomething中的方法的,所以委托和这些方法的签名要一致。

            public delegate void MyDelegate(object sender, CustomeEvetnArgs e);
    于是有了这个助手,green轻松多了,他终于不用管今天是星期几了,我们重新改一下player类,这个类中去掉了thedate属性,也没有了if,只有一个委托oncomplete事件在运动员OnComplete时触发

    public class player
            ...{
                private string _code;
                public string Code
                ...{
                    get ...{ return _code; }
                    set ...{ _code = value; }
                }
                public event MyDelegate oncomplete;
                public void OnComplete()
                ...{
                    CustomeEvetnArgs e = new CustomeEvetnArgs();
                    e.Code = this.Code;
                    if (oncomplete != null)
                    ...{ oncomplete(this, e); }
                }
            }
    而这个助手要看今天是星期几,然后执行相应的方法,date是今天的日期。

                DoSomeThing things = new DoSomeThing();
                if (date == "Mon")
                ...{ green.oncomplete += new MyDelegate(things.GiveCodeToManager); }
                if (date == "Tues")
                ...{ green.oncomplete += new MyDelegate(things.RecodeCode); }
                if (date == "Wed")
                ...{ green.oncomplete += new MyDelegate(things.GiveCodeToOthers); }
                green.OnComplete();
                Response.Write(result);
    这样万一游戏流程有了改变,那也跟green无关了,他只要专心训练,其他的由这个助手进行改动。

    委托可以通过+= ,-=来增加和消除他在星期几所委托的方法。

    高聚合 低耦合,是委托的一个很重要的用途。

    大家也可以点击我的博客(点我的头像)查看,有兴趣的可以一起讨论
    30  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • yagebu1983
    • 等级:
    发表于:2008-05-23 11:07:461楼 得分:1
    学习了!!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 11:29:482楼 得分:1
    潜在精化帖,留名再看
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Jinglecat
    • 等级:
    发表于:2008-05-23 11:33:023楼 得分:1
    委托可以通过+= ,-=来增加和消除他在星期几所委托的方法。

    ============

    +=/-= 是特定语言的实现,

    委托不是C#独有,其他.NET语言也可以实现委托链
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 11:36:214楼 得分:1
    学习~~`
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • ojlovecd
    • 等级:
    发表于:2008-05-23 11:41:135楼 得分:1
    好东西,非常感谢楼主分享知识的精神,mark,学习
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Berny
    • 等级:
    发表于:2008-05-23 11:42:066楼 得分:1
    不错不错,很生动!留名......
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 11:44:037楼 得分:1
    我的理解
    委托就是函数指针,函数别名
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 11:59:118楼 得分:1
    呵呵  很支持楼主的这股精神

    暂没时间详看

    下次再来
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 12:02:089楼 得分:0
    多谢大家帮顶,只要这个帖子能对大家有一些作用,就好。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 12:31:1110楼 得分:1
    站个位置。  回头再看
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • lfywy
    • 等级:
    发表于:2008-05-23 12:36:4711楼 得分:1
    mark下!回头仔细看!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 13:02:3212楼 得分:1
    不错,学习了,就是把应该自己的作的事情交给别人做了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 13:14:2913楼 得分:1
    顶住
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 13:18:2114楼 得分:1
    支持原创
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 13:21:1815楼 得分:1
    bucuo
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 13:35:5716楼 得分:1
    支持一下
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 13:39:4017楼 得分:1
    学习了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 13:47:5618楼 得分:1
    up
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 16:08:5419楼 得分:1
    很好很強大
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 16:12:3320楼 得分:1
    mark
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 16:22:3021楼 得分:1
    sov楼主高聚合 低耦合怎么理解?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 16:34:2022楼 得分:1
    學習中
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 16:38:0023楼 得分:1
    不错
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 16:51:1524楼 得分:1
    up
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 16:53:5425楼 得分:0
    to 21楼
    高聚合低耦合 是为了降低程序出错的几率,和提高代码的可读性考虑的。
    不单单在c#中应用,广泛的讲,高聚合在于提高程序模块之间的聚合度
    低耦合在于降低子程序之间的耦合度。
    在c#中分别体现在类的属性方法以及类与类之间的关系上。
    我的理解,权且当作 抛砖引玉
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 17:15:1326楼 得分:1
    委托和事件是必学科目啊
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 17:16:3027楼 得分:1
    顶!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 17:19:3328楼 得分:1
    jf
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 17:20:2729楼 得分:1
    jf
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 17:21:1030楼 得分:1
    jf
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 17:31:4931楼 得分:1
    看了 还不错
    以前是专门为了写个消息触发而做委托
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-23 18:33:0232楼 得分:1
    学习~
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-24 16:14:5933楼 得分:0
    學習
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-24 16:28:2734楼 得分:0
    烙个脚印
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-24 17:25:1935楼 得分:0
    先顶再看`