• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
冥海
博客园    首页    新随笔    联系   管理    订阅  订阅

我看委托(三)

1.委托
写程序的时候,根据传递的参数,确定调用的是哪个函数,但我有一点疑问,委托的对象不是指向函数名,委托的参数不是和函数名的参数一样,那么这样为什么还不能确定调用的是哪个方法呢?

委托可以认为具有相同签名和返回值类型的有序方法列表。
当委托被调用时,它调用方法列表中的每一个方法。

第一步:声明委托
delegate 返回值类型  委托类型名(参数名); 没有方法主体
delegate void adelegate(string a);


第二步:既然委托没有方法主体,那么我就要声明一个方法主体,否则将没有任何意义。
这个时候,就可以根据委托来进行方法的声明。
static 返回值类型 方法名(参数名)
{
方法主体
}

static void Say(string a)
{
  Console.WriteLine("aaa");
}


第三步:在程序中进行委托的调用
既然是进行委托的调用,那么委托对象首先要指向要调用的方法,如果委托没有指向任何方法名,那么也就谈不上委托对方法列表进行调用了。
★★★委托类型声明委托对象如何对方法进行调用呢?可以有这两种方法。
1)直接声明一个委托对象然后指向要调用的方法名即可。
adelegate adel = Say;
adel("11");
2)实例化一个委托对象,把方法名当做参数传递过去,然后在进行委托的调用。
adelegate adel = new adelegate(Say);
adel("11");


2.委托如何调用多个方法
★★★★★上面说的是委托对方法列表中的一个方法进行调用,那么能不能对多个方法进行调用呢?当然是可以的了,委托的一个特重要的目的就是对多个方法一起进行调用。

adelegate adel = new adelegate(Say)+Hellow; //进行多个方法的调用时,委托指向的第一个方法必须被实例化。
adel("11");


static void Say(string a)
{
            Console.WriteLine("aaa");
}

static void Hellow(string b)
{
           Console.WriteLine("bbb");
}

delegate void adelegate(string a);

★★★★★通过上面的例子我们可以看出,委托是如何对多个方法进行调用的。


3.下面我们通过一个例子,可以更进一步看出委托是如何扣窟窿的。
List<int> list1 = new List<int>();
list1.Add(10);
list1.Add(-15);
list1.Add(14);
list1.Add(-8);
list1.Add(6);
list1.Add(3);


foreach (int i in list1)
{
     if (i > 10)
      {
        Console.WriteLine("i大于10的{0}",i);
      }
}


foreach (int i in list1)
{
     if (i%2==0)
      {
        Console.WriteLine("i为偶数的{0}",i);
      }
}

foreach (int i in list1)
{
   if (i< 0)
     {
        Console.WriteLine("i小于0的{0}",i);
     }
}
★★★★★通过上面的例子,我们发现没次对i进行判断,都要进行一次循环声明,如果细心点会发现,上面唯一不同的地方是if条件的判断。

4.通过一个WinForm程序引入事件的概念
(1)一个简单的委托在窗体间调用的例子
第一步:在用户控件中自定义一个按钮,声明委托,委托的对象,当用户点击自定义按钮时,如果委托不为null的时候,调用用户传递过来的委托方法。
public delegate void adelegate();  //声明一个委托


public adelegate adel;//声明一个委托对象。
private void button1_Click(object sender, EventArgs e)
{
    if (adel != null)
     {
         adel();
     }
}


(2)在窗体中的构造函数中,声明当前用户控件btnuser的委托指向的方法是
btnuser.adel = Say;

(3)然后声明委托调用的方法
void Say()
{
            MessageBox.Show("点击了");
}


5.如何进行委托的清除如伪造
对使用的控件进行修改
btnuser.adel = null; //清除用户控件的委托为空null

if(btnuser.adel!=null) //如果用户控件的委托不为空的话
btnuser.adel(); //进行用户控件的冒充

★★★★★既然存在着这样的问题,那么如何进行保护呢,避免可能出现的清除与监听呢?
(1)如果把声明委托的对象改成private的话,那么虽都无法进行访问,这种方法,显然是不好的。

那么如何进行避免呢,可以有以下两种方法,把委托声明为私有的,在方法中进行添加委托的调用。
private adelegate adel;
public void Ade(adelegate d)
{
   adel += d;
}

内部使用的还是私有的委托对象。
if (adel != null)
{
   adel();
}

★★★★★但外部的话,就需要通过方法传递调用列表了。
btnuser.Ade(Say);  用户控件 委托方法(调用列表中的方法名)

(2)使用事件来避免清除与冒充
★★★★★委托是类型,事件是用委托来实现的其实就是字段或属性。
event 委托类型  事件名{add remove}
事件成员可以用+=、-=调用add、remove方法

public event SanQiangDelegate OnSanQiang
{
//add remove最终也是编译生成两个方法
//当用户sanQiangButton1.OnSanQiang += _SAnQiang1添加监听的时候
//就会调用add方法,value就是添加的委托
 add
 {
   _onSanQiang += value;
 }

 remove
 {
  _onSanQiang -= value;
 }
}

★★★★★外部使用事件的时候,必须+= 或-=
btnuser.adel += Say;

posted @ 2011-04-18 11:04  冥海  阅读(132)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3