C# 委托
1.委托定义
(1)委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。
(2)利用委托实现封装与隔离,通过委托调用更灵活
(3)委托是类型,与class同级,所以可定义在类外 ,委托类型规定方法的签名(方法类型):返回值类型,参数类型、个数、顺序。委托变量用来存储方法的引用
2.委托的使用
(1)定义委托:[访问修饰] delegate 返回类型 委托名(参数列表)
委托参数中目前语法不能省略参数名
(2)实例化委托:
委托类型 委托变量=new 委托名(方法名)或者
委托类型 委托变量=方法名
(3)使用委托:
委托间接调用方法,增加了变数,同一段代码,委托方法不一样,执行效果就不一样
3.委托例程
(1)例程1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WFM_Thread
{
//定义委托
public delegate double Cal(double x, double y);
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
double sum(double d1, double d2)
{
return d1 + d2;
}
double avg(double d1, double d2)
{
return (d1 + d2) / 2;
}
private void button1_Click(object sender, EventArgs e)
{
//实例化委托
Cal cal = new Cal(sum);
//使用委托
double n1 = cal(4, 5);
Console.WriteLine(n1);
//实例化委托
Cal cal2 = avg;
//使用委托
double n2 = cal2(4, 4);
Console.WriteLine(n2);
}
//第二个小例子
static void Test(Cal f)
{
double result = f(4,8);
Console.WriteLine(result);
}
private void button2_Click(object sender, EventArgs e)
{
Cal f = new Cal(sum);
Test(f);
}
}
}
(2)例程2:通过创建线程,实现点击按钮,文本框中显示文字。
//定义一个委托
public delegate void ButtonEventHandler();
ButtonEventHandler buttonEventHandler;
private void button2_Click(object sender, EventArgs e)
{
//实例化委托
buttonEventHandler = new ButtonEventHandler(addText);
Thread thread = new Thread(run2);
thread.Start();
}
public void addText()
{
textBox2.Text = "hello world";
}
public void run2()
{
//触发委托
this.Invoke(buttonEventHandler);
}
(3)上述方法是通过创建线程,实现点击按钮,文本框中显示文字,也可以直接使用委托
//定义一个委托
public delegate void ButtonEventHandler();
private void button2_Click(object sender, EventArgs e)
{
//实例化委托
ButtonEventHandler buttonEventHandler = new ButtonEventHandler(addText);
buttonEventHandler.Invoke();
}
public void addText()
{
textBox2.Text = "hello world";
}
注意点:这并不意味着委托可以替代线程去执行,下面这个例子是线程+委托实现向listbox中添加数字。页面不会卡顿。
private void button2_Click(object sender, EventArgs e)
{
Thread thread = new Thread(run3);
thread.Start();
}
public void run3()
{
for (int i = 0; i < 100000; i++)
{
listBox1.Invoke(new Action(() => { listBox1.Items.Add(i); }));
}
}
下面这个例程,页面卡顿
public delegate void DD();
private void button4_Click(object sender, EventArgs e)
{
DD dD = new DD(rundd);
dD.Invoke();
}
public void rundd()
{
for (int i = 0; i < 100000; i++)
{
listBox1.Items.Add(i);
}
}
或者换一种委托方式,页面也卡顿
public delegate void DD(int i);
private void button4_Click(object sender, EventArgs e)
{
DD dD = new DD(rundd);
for (int i = 0; i < 10000; i++)
{
dD.Invoke(i);
}
}
public void rundd(int i)
{
listBox1.Items.Add(i);
}
正确的使用方法是线程搭配委托,以下,页面不卡顿
public delegate void DD(int i);
DD dD;
private void button4_Click(object sender, EventArgs e)
{
dD = new DD(rundd);
Thread thread=new Thread(DO);
thread.Start();
}
public void rundd(int i)
{
listBox1.Items.Add(i);
}
public void DO()
{
for (int i = 0; i < 10000; i++)
{
this.Invoke(dD, i);
}
}
这种委托+线程,页面会卡顿
public delegate void DD();
DD dD;
private void button4_Click(object sender, EventArgs e)
{
dD = new DD(rundd);
Thread thread=new Thread(DO);
thread.Start();
}
public void rundd()
{
for (int i = 0; i < 10000; i++)
{
listBox1.Items.Add(i);
}
}
public void DO()
{
this.Invoke(dD);
}