想把要调用的函数定义为一个变化的参数,把要它逐个处理的函数定义为一个参数,我传递哪个参数,它就调用哪个参数
View Code
//1先声明一个委托 delegate string DelMethod(string str); static void Main(string[] args) { string[] strs = { "AAVV", "ChWn", "FFccc", "aaJJ" }; //2定义委托,让委托指向方法 DelMethod del = new DelMethod(ToUpper); //3调用委托 StringProcess(strs, del); Console.WriteLine(string.Join("-",strs)); } static void StringProcess(string[] strs,DelMethod del) { for (int i = 0; i < strs.Length; i++) { strs[i] = del(strs[i]); } } static string ToLower(string str) { return str.ToLower(); } static string ToUpper(string str) { return str.ToUpper(); }
让委托指向方法,可以直接这么写DelMethod del = ToUpper;
熟练后就可以 直接使用StringProcess(strs, Toupper);
只要声明一个委托,让它的签名与方法一样,那么把委托作为参数时就可以调用那个方法了;
还可以直接写个匿名方法来使用委托:
DelMethod del = delegate(string str) { return str.ToUpper(); };
第一个例子,我们要比较int数组里最大的数、字符串里最长的数、Person类里年龄最大的数,使用委托来实现:
View Code
class Person { public Person() { } public Person(string name, int age) { this.name = name; this.age = age; } private string name; public string Name { get { return name; } set { name = value; } } private int age; public int Age { get { return age; } set { age = value; } } public override string ToString() { return name; } } class Program { static void Main(string[] args) { object[] objInt = {1,2,3,4,5,6,7 }; object[] objString = { "a", "ab", "abc", "abcd" }; object[] objPerson = { new Person("张三", 15), new Person("李四", 21), new Person("老五", 30) }; Console.WriteLine(GetMax(objInt, IntCompare)); Console.WriteLine(GetMax(objString, StringCompare)); Console.WriteLine(GetMax(objPerson, PersonCompare)); Console.ReadKey(); } delegate int DelMethod(object o1,object o2); static int PersonCompare(object o1, object o2) { Person num1 = (Person)o1; Person num2 = (Person)o2; return num1.Age - num2.Age; } static int StringCompare(object o1, object o2) { string num1 = (string)o1; string num2 = (string)o2; return num1.Length - num2.Length; } static int IntCompare(object o1, object o2) { int num1 = (int)o1; int num2 = (int)o2; return num1 - num2; } static object GetMax(object[] arr,DelMethod del) { object Max=arr[0]; for (int i = 0; i < arr.Length; i++) { if (del(Max,arr[i])<0) { Max = arr[i]; } } return Max; } }
第二个例子,跟上面的一样,只是我们是要排序,把他们按从小到大的顺序输出来:
这里是用冒泡算法来排序的
class Person { public Person() { } public Person(string name, int age) { this.name = name; this.age = age; } private string name; public string Name { get { return name; } set { name = value; } } private int age; public int Age { get { return age; } set { age = value; } } public override string ToString() { return name; } } class Program { static void Main(string[] args) { object[] objInt = {1,2,3,4,5,6,7 }; object[] objString = { "a", "ab", "abc", "abcd" }; object[] objPerson = { new Person("张三", 15), new Person("李四", 21), new Person("老五", 30) }; Sort(objInt, IntCompare); Sort(objString, StringCompare); Sort(objPerson, PersonCompare); Console.WriteLine(string.Join("-", objInt)); Console.WriteLine(string.Join("-", objString)); Console.WriteLine(string.Join("-", objPerson)); Console.ReadKey(); } delegate int DelMethod(object o1,object o2); static int PersonCompare(object o1, object o2) { Person num1 = (Person)o1; Person num2 = (Person)o2; return num1.Age - num2.Age; } static int StringCompare(object o1, object o2) { string num1 = (string)o1; string num2 = (string)o2; return num1.Length - num2.Length; } static int IntCompare(object o1, object o2) { int num1 = (int)o1; int num2 = (int)o2; return num1 - num2; } static void Sort(object[] arr, DelMethod del) { bool isChanged = false; for (int i = 0; i < arr.Length; i++) { isChanged = false; for (int j = 0; j < arr.Length-1-i; j++) { if (del(arr[j], arr[j + 1])>0) { object item = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = item; isChanged = true; } } if (!isChanged) break; } } }
第三个例子,我们使用系统带的排序方法;
系统里带的Sort排序方法,数字是从小到大排序的,字符串是按从a到z排序的;
Sort()方法参数有个委托参数,public delegate int Comparison<in T>(T x, T y);所以我们可以按照它的签名来写一个方法,实现我们想要的排序
Sort方法
class Person { public Person() { } public Person(string name, int age) { this.name = name; this.age = age; } private string name; public string Name { get { return name; } set { name = value; } } private int age; public int Age { get { return age; } set { age = value; } } public override string ToString() { return name; } } class Program { static void Main(string[] args) { List<int> listInt = new List<int>{1,2,3,4,5,6,7 }; List<string> listString = new List<string>() { "d", "ba", "cba", "dcba" }; List<Person> listPerson = new List<Person>() { new Person("张三", 15), new Person("李四", 21), new Person("老五", 30) }; listInt.Sort(); listString.Sort(StringCompare); listPerson.Sort(PersonCompare); Console.WriteLine(string.Join("-", listInt)); Console.WriteLine(string.Join("-", listString)); Console.WriteLine(string.Join("-", listPerson)); Console.ReadKey(); } static int StringCompare(string s1, string s2) { return s1.Length - s2.Length; } static int PersonCompare(Person p1, Person p2) { return p1.Age - p2.Age; } }
可以使用委托实现用户登录控件,让不同的窗体使用时可以实现不同的操作(调用不同的数据库来操作);
委托是一个数据类型,要实例化后才能调用
//1声明委托 public delegate void DelMethod(string userName, string pwd); //2让委托指向方法 public DelMethod del; private void button1_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(textBox1.Text)) { MessageBox.Show("用户名不能为空"); } else if (string.IsNullOrEmpty(textBox2.Text)) { MessageBox.Show("密码不能为空"); } else { //DelMethod(textBox1.Text, textBox2.Text)这么写不对 if (del != null)//委托指向的方法不为null时; { //3.调用委托 del(textBox1.Text, textBox2.Text); } } }
给委托添加方法
private void Form1_Load(object sender, EventArgs e) { ucLogin1.del = new UCLogin.DelMethod(Login); } static void Login(string user, string pwd) { if (user == "admin" && pwd == "admin") { MessageBox.Show("登陆成功"); } else { MessageBox.Show("用户名密码不正确"); } }
为什么说事件就是委托,可以使用反编译看一下,事件其实就是封装了委托,还有两个方法;跟属性差不多。
使用事件来实现上面的用户登录的例子:
用事件实现
public delegate void DelMethod(string name, string pwd); public event DelMethod del;//定义一个事件 private void button1_Click_1(object sender, EventArgs e) { if (string.IsNullOrEmpty(textBox1.Text)) { MessageBox.Show("用户名不能为空"); return; } else if (string.IsNullOrEmpty(textBox2.Text)) { MessageBox.Show("密码不能为空"); return; } else { if (del != null) { del(textBox1.Text, textBox2.Text); } } }
View Code
private void Form1_Load(object sender, EventArgs e) { //+=后面直接两个Tab键就可以添加事件了 ucLogin1.del += new UCLogin.DelMethod(ucLogin1_del); } void ucLogin1_del(string name, string pwd) { if (name == "admin" && pwd == "admin") { MessageBox.Show("登陆成功"); } else { MessageBox.Show("用户名密码不正确"); } }