《委托的使用示例》
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 委托的本质
{
public delegate void MyDelegate(); //定义一个委托
public class Test
{
//委托说白了就是一个数据类型,就像string 类型接收字符串数据 int类型接收整形数据, 而委托类型接收方法
public string Name { get; set; } //定义一个属性
public MyDelegate mydele; //定义一个委托变量
public int i; //定义一个整形变量
public Test abc; //定义一个Test类型的变量。
public void MyTest(string str,MyDelegate myde)
{
//我在Main 函数中调用 这个MyTest方法,注意,我们传递了两个参
//此时: str的值为:"张三" 这个字符串
//此时: myde的值为:Program.Pro 这个方法 (所以,这里是把Program.Pro这个方法当做一个参数在传递)
this.Name = str; //此时Name的值就是“张三”这个字符串
this.mydele = myde; //此时的mydele的值就是Program.Pro方法了。(如果给this.mydele赋了值,在当前方法以外,我们就可以使用mydele这个委托了,比如在Haha()方法中,当然在当前方法中也可以直接用,比如直接执行myde委托,货这执行赋了值之后的this.mydele委托)
}
public void Haha()
{
this.mydele();
}
}
class Program
{
public static void Pro()
{
Console.WriteLine("嗨!我是一个方法!");
}
static void Main(string[] args)
{
Test t = new Test();
t.MyTest("张三", Program.Pro);
t.Haha();
Console.Read();
}
}
}
//类是一种数据类型,它是用来存储类的对象的
public class MyClass //类的定义方式
MyClass c=new MyClass(); //类的使用方式
//委托也是一种数据类型,委托这个数据类型用来存储方法的。
public deletage void MyDelegate() //委托的定义方式
//既然委托是用来存储方法的,声明一个委托类型,new一个就可以存储一个方法
MyDelegate myde=new MyDelegate(这里是一个无参,无返回值的方法) //委托的使用方式
<pre class="csharp" name="code">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 委托
{
//委托可以定义在类里面,但是一般我们不那样做,除非特殊情况。因为委托是和类平级的,所以委托一般定义在namespace下面
//定义一个委托,用来保存无返回值,无参数的方法
public delegate void MyDelegate();
class Program
{
public void M1()
{
Console.WriteLine("哈哈!");
}
static void Main(string[] args)
{
Program p = new Program();
MyDelegate md = new MyDelegate( p.M1);
//上面这一步我们可以简写 直接写成 MyDelegate md=p.M1 就行;但是委托对象一定是要赋值给一个委托对象的,在这里看起来是直接把p.M1 这个方法赋值给md对象了。其实是编译器内部会给我们new了一个委托对象的,也就是说编译器自动给我们完成了MyDelegate md = new MyDelegate( p.M1);
Console.WriteLine("..............................");
Console.WriteLine("..............................");
md(); //这里使用委托简直的多此一举,我们直接调用M1方法就可以了。没有必要在这里使用委托。但是这里我们仅仅是演示一下委托的使用而已
Console.WriteLine("..............................");
Console.WriteLine("..............................");
Console.WriteLine("OK");
Console.ReadKey();
}
}
}
《委托的使用场合1----挖坑,填坑》
新建一个解决方案。
1,在里面创建一个类库。默认命名为:ClassLibrary1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClassLibrary1
{
public class TestClass1
{
public void DoSomething()
{
Console.WriteLine("..........................");//这里可能是连接数据库的操作代码
Console.WriteLine("..........................");//这里可能是对文件操作的代
Console.WriteLine(DateTime.Now.ToString()); //在这里输出当前时间
Console.WriteLine("..........................");
Console.WriteLine("..........................");
Console.WriteLine("OK");
Console.ReadKey();
}
}
}
下面我们创建一个控制台应用程序 命名为:TestDelegateApp1,并给它添加引用ClassLibrary1这个类库
using ClassLibrary1;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestDelegateApp1
{
class Program
{
static void Main(string[] args)
{
TestClass1 tc = new TestClass1();
tc.DoSomething();
}
}
}
执行TestDelegateApp1这个控制台项目,产生了如下输出:
接着,我们在解决方案下面,再添加一个控制台应用程序,命名为:TestDelegateApp2
在TestDelegateApp2这个控制台应用程序里我的需求变了:还是输出上面那一幅图里面的虚线,但是中间那一行日期不在进行输出了,而是将中间那一行日起写入到一个文件中,如果这样的话,我们就需要修改ClassLibrary1这个类库的TestClass1.cs文件。将它修改为
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClassLibrary1
{
public class TestClass1
{
public void DoSomething()
{
Console.WriteLine("..........................");//这里可能是连接数据库的操作代码
Console.WriteLine("..........................");//这里可能是对文件操作的代
File.AppendAllText(@"d:\nono.txt",DateTime.Now.ToString());
Console.WriteLine("..........................");
Console.WriteLine("..........................");
Console.WriteLine("OK");
Console.ReadKey();
}
}
}
然后再TestDelegateApp2这个控制台中也引用一下ClassLibrary1这个类库,
using ClassLibrary1;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestDelegateApp2
{
class Program
{
static void Main(string[] args)
{
TestClass1 tc = new TestClass1();
tc.DoSomething();
}
}
}
运行TestDelegateApp2这个控制台应用程序,产生如下输出:
在去D盘下的nono.txt文件看看,当前时间也已经写入了
-----------------------------------------------------------------------------------------------------------
那么问题来了。每次我变化一下需求,就要改一下ClassLibrary1类库中的代码,而且我的项目中,有好几处都需要调用ClassLibrary1这个类库中的TestClass1.cs这个类中的DoSomething方法,而大家仅仅是对日期那一部分有不同的需要而已,如果大家都改ClassLibrary1类库中的TestClass1类中的DoSomething()方法是不合适的。
于是我们想到一个办法。那就是使用委托,将日期那一部分用一个委托代替(我们知道委托是存储方法的),谁有不同的需求,就实现这个委托不就得了?
那下面我就将ClassLibrary1类库中TestClass类中的DoSomething()方法改成如下这样:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClassLibrary1
{
public delegate void Mydelegate();
public class TestClass1
{
public void DoSomething(Mydelegate myde)
{
Console.WriteLine("..........................");//这里可能是连接数据库的操作代码
Console.WriteLine("..........................");//这里可能是对文件操作的代
myde(); //在这里放一个委托。谁想在这里实现什么功能,只要去实现这个委托就好了(委托就像母版页一样,在这里挖一个坑,想实现什么功能,就来填坑)
Console.WriteLine("..........................");
Console.WriteLine("..........................");
Console.WriteLine("OK");
Console.ReadKey();
}
}
}
然后我们再看看TestDelegateApp1控制台应用程序的代码
using ClassLibrary1;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestDelegateApp1
{
class Program
{
public static void abc()
{
Console.WriteLine(DateTime.Now.ToString());
}
static void Main(string[] args)
{
TestClass1 tc = new TestClass1();
tc.DoSomething(abc);
}
}
}
再来看看TestDelegateApp2这个控制台应用程序的代码:
using ClassLibrary1;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestDelegateApp2
{
class Program
{
public static void abc()
{
File.AppendAllText(@"d:\nono.txt", DateTime.Now.ToString());
}
static void Main(string[] args)
{
TestClass1 tc = new TestClass1();
tc.DoSomething(abc);
}
}
}
《委托的使用场合2----挖坑,填坑》
新建一个解决方案。
1,在里面创建一个类库。默认命名为:ClassLibrary1
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClassLibrary1
{
public delegate string Mydelegate(string str);
public class TestClass1
{
public void ChangeStrings(string[] str,Mydelegate myde)
{
for (int i = 0; i < str.Length; i++)
{
//需求:我要对str这个数组的项进行处理
//1,将str这个数组的每一项前后都加一个* 在TestDelegateApp1这个控制台应用程序里实现这个功能
//2, 将str这个数组的小写字母,全转换成大小字母, 在TestDelegateApp2这个控制台应用程序里实现这个功能
Console.WriteLine(str[i] = myde(str[i]));//我在这里有使用委托你看的出来吗? 将委托的放回值赋值给str的每一项,就实现这个目的了
}
Console.ReadKey();
}
}
}
using ClassLibrary1;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestDelegateApp1
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
string[] str = new string[] { " 张三", " 李四", " 王五", " 赵六" };
TestClass1 tc = new TestClass1();
for (int i = 0; i < str.Length; i++)
{
tc.ChangeStrings(str, abc);
}
}
public static string abc(string s)
{
return "*" + s + "*";
}
}
}
执行TestDelegateApp1这个控制台项目,产生了如下输出:
接着,我们在解决方案下面,再添加一个控制台应用程序,命名为:TestDelegateApp2
using ClassLibrary1;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestDelegateApp2
{
class Program
{
public static void abc()
{
}
static void Main(string[] args)
{
string[] str = new string[] { "zhangshang", "lisi", "wangwu", "zhaoliu" };
TestClass1 tc = new TestClass1();
for (int i = 0; i < str.Length; i++)
{
tc.ChangeStrings(str, abc);
}
Console.ReadKey();
}
public static string abc(string name)
{
return name.ToUpper();
}
}
}
《委托单使用场合3----窗体之间传值》
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 委托案例_窗体之间通过委托传值
{
public delegate void UpdateFrom1TextBox(string s);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2(textBox1.Text, UpdateTextBox);//创建Fom2类对象,将UpdateTextBox方法作为参数来传递到From2类中,用于初始化From2类中的委托变量。(注意;委托变量接收的是方法,所以要初始化Form2中的委托变量,就要让它接收一个方法,所以这里我们传递一个方法过去)
f2.Show();
}
//写这个方法的目的是在Form2窗体中跟新Form1窗体(当前窗体)中的TextBox1的值 (因为我在Form2窗体的构造函数中重载了一个带2个参数的Form2窗体的构造函数;第一个参数是一个string类的值,第二个参数是一个委托,,我们在From1类中创建一个Form2类的对象,然后传递2个参数,它就会自动的调用带2个参数的构造函数了。既然是第二个参数是一个委托,这样就可以将这个方法当做参数传递过去,然后再From2中定义一个委托变量,在这个带两个参数的构造函数执行的时候,我再给Form2类中的的那个委托变量赋值为传过去的方法(即当前这个方法),然后再Fom2类中去执行这个委托,而执行这个委托就是执行UpdateTextBox这个方法。所以就实现了在Form2类中更新Form1类的中的TextBox值了)
private void UpdateTextBox(string value)
{
textBox1.Text = value;
}
}
}
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 委托案例_窗体之间通过委托传值
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();//这句话是初始化对象窗口
}
//因为委托是与类同一级别的,它一般是定义在namespace下面,所以Form1类与Form2类都可以访问它(注意:窗体1是Form1类,和窗体2是Form2类 都是在同一名称空间下)
public Form2(string str,UpdateFrom1TextBox update)
{
InitializeComponent();
this.textBox1.Text = str;
this._update = update; //因为在Form1类中button1_Click事件中创建了一个Form2的类对象,是调用的Form2类带2个参数的构造函数,即当前的这个构造函数:Form2 f2 = new Form2(textBox1.Text, UpdateTextBox); 因为当前构造函数的第二个参数是一个委托类型,而委托类型是存储方法的,而正好这里又在Form1类中创建的这个Form2类对象的时候 传递了一个UpdateTextBox方法过来。 这里的this._update = update 就表示给当前类下的这个_update委托变量初始化赋值。赋的什么值呢?答:赋的是从Form1类中传过来的UpdateTextBox方法。
}
private UpdateFrom1TextBox _update; //定义一个委托变量。
private void button1_Click(object sender, EventArgs e)
{
this._update(textBox1.Text); //这里执行_update这个委托,其实就是执行UpdateTextBox这个方法。所以在执行this.Close()关闭当前窗口之前,会执行UpdateTextBox这个方法 (这个方法就是更新Form1类中的TextBox1的值)
this.Close();
}
}
}