委托本质是C语言中的函数指针
using System;
namespace _01_委托
{/// <summary>
/// 委托是一个数据类型,可以定义变量
/// 委托定义变量和类非常相似,它是用来存储方法的
/// </summary>
class Program
{
static void Main(string[] args)
{
//2、使用委托第二步:声明委托变量,并赋值。
//声明了一个委托变量md,并且new了一个委托对象,并且把方法M1传递进去
//即md委托保存了M1方法。
MyDelegate md = new MyDelegate(M1);
//3、调用了md委托的时候就相当于调用了M1方法。
md();
Console.WriteLine("ok");
Console.ReadKey();
}
static void M1()
{
Console.WriteLine("我是没有返回值,没有参数的方法");
}
}
//1、使用委托第一步:定义委托类型
//定义了一个委托类型,用来保存无参数,无返回值的方法
//定义了一个名字叫MyDelegate的类型,是个委托,只能存储无返回值,无参数的方法
public delegate void MyDelegate();
}
以上是委托的使用过程:
1、先定义
2、赋值
3、使用
案例:先创建一个类TestClass,该类中有DoSomething方法(假设有5条语句),调用该类的对象时,DoSomething方法当然操作都相同。但是,现在第三条语句打印系统时间,可能是打印到中控台,也可能是写到文件里,也可能是写到数据库里等等很多种可能,我们不能列举所有的可能,通过委托来实现。
using System;
namespace 委托使用案例
{
public class TestClass
{
public void DoSomething(WrieTimeDelegate writeTime)
{
Console.WriteLine("=========================");
Console.WriteLine("=========================");
//将下一行代码写活,不要写死
//Console.WriteLine(System.DateTime.Now.ToString());
//writeTime();
if(writeTime!=null)
{
writeTime();
}
Console.WriteLine("=========================");
Console.WriteLine("=========================");
}
//public void ChangeStrings(string [] strs)
//{
// for (int i = 0; i < strs.Length; i++)
// {
// strs[i] = "★" + strs[i] + "★";
// }
//}
public void ChangeStrings(string[] strs,GetStringGelegate change)
{
for (int i = 0; i < strs.Length; i++)
{
strs[i] = change(strs[i]);
}
}
public delegate string GetStringGelegate(string name);
//定义一个委托,一个用来存储没有返回值,没有参数的委托
public delegate void WrieTimeDelegate();
}
}
//举例:button按钮是一个类,点击button可以连数据库,也可以连接文件,也可以弹出对话框等,做什么都可以,不需要定义不同的方法,按钮类内部就是通过内部一系列不同的委托来实现的不同功能
打印到中控台
using System;
using 委托使用案例;
namespace _01_控制台打印
{
class Program
{
static void Main(string[] args)
{
TestClass tc = new TestClass();
//DoSomething的参数是一个方法名PrintToConsole,用C语言的理解话,就是类中的函数指针指向了PrintToConsole方法
tc.DoSomething(PrintToConsole);
Console.ReadKey();
}
//
static void PrintToConsole()
{
Console.WriteLine(System.DateTime.Now.ToString());
}
}
}
打印到文件:
using System;
using System.IO;
using 委托使用案例;
namespace _02_写到文本文件里
{
class Program
{
static void Main(string[] args)
{
TestClass tc = new TestClass();
//写到文件里,WriteToFiel作为参数
tc.DoSomething(WriteToFiel);
Console.ReadKey();
}
static void WriteToFiel()
{
File.WriteAllText("time.txt", System.DateTime.Now.ToString());
}
}
}
案例:还是在类TestClass中,通过不同的方法ChangeStrings或者ChangeStrings1做参数,实现大写或者小写。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 委托使用案例;
namespace _03_委托_字符串举例
{
class Program
{
static void Main(string[] args)
{
TestClass tc = new TestClass();
string[] names = new string[] { "ZhangSan", "LiSi", "WangWu" };
tc.ChangeStrings(names,ChangeStrings);
for (int i = 0; i < names.Length; i++)
{
Console.WriteLine(names[i]);
}
Console.ReadKey();
}
static string ChangeStrings(string name)
{
return name.ToUpper();
}
static string ChangeStrings1(string name)
{
return name.ToLower();
}
}
}
匿名:
using System;
namespace _02_匿名方法
{
public delegate void MyDelegate();
public delegate void MyDelegate1(string msg);
public delegate int MyDelegate2(int x, int y);
class Program
{
static void Main(string[] args)
{
//匿名方法
//匿名方法不在类中定义,而是在给委托变量赋值的时候,需要赋值一个方法,用现做现卖的方式,定义一个匿名方法传递给委托
Console.WriteLine("这是正常的委托方法使用");
MyDelegate md = M1;
md();
Console.WriteLine("=====================");
Console.WriteLine("无参数无返回值的匿名方法");
MyDelegate mdd = delegate ()
{
Console.WriteLine("匿名方法打印的:OK!");
};
mdd();
//有参数无返回值的匿名方法
Console.WriteLine("=====================");
MyDelegate1 md1 = delegate (string msg)
{
Console.WriteLine("有参数无返回值的匿名方法打印的:" + msg);
};
md1("OK");
//有参数有返回值的匿名方法
Console.WriteLine("=====================");
MyDelegate2 md2 = delegate (int x, int y)
{
return x * x + y * y;
};
Console.WriteLine("有参数无返回值的匿名方法打印的{0}:", md2(3, 4));
//无参数无返回值的匿名方法用lambda表达式写法
Console.WriteLine("=====================");
MyDelegate m = () => { Console.WriteLine("lambda表达式"); };
m();
//有1个参数无返回值的匿名方法用lambda表达式写法,lambda表达式从来不需要传数据类型的
Console.WriteLine("=====================");
MyDelegate1 m1 = mm => { Console.WriteLine(mm); };
m1("are you ok?");
//有多个参数无返回值的匿名方法用lambda表达式写法,lambda表达式从来不需要传数据类型的
Console.WriteLine("=====================");
MyDelegate2 m2 = (x, y) => { return (x + y); };
int temp = m2(3, 4);
Console.WriteLine(temp);
//
Console.ReadKey();
}
static void M1()
{
Console.WriteLine("OK!");
}
}
}
泛型委托:
using System;
namespace _03_泛型委托
{
public delegate void MyGenericDelegate<T>(T args);
class Program
{
static void Main(string[] args)
{
//Action:无返回值的委托,系统给的
//Action<>:无返回值的委托,泛型版本的,最多16个参数
//Func<>:有返回值的委托,没有非泛型版本的
//MyGenericDelegate<string> md = M1;
//md("aaa");
Action<string> a1 = m => { Console.WriteLine(m); };
a1("雷猴");
Action<int, int> a2 = (x, y) => { Console.WriteLine(x + y); };
a2(3, 5);
//Func<>:有返回值的委托,没有非泛型版本的,最多8个参数,返回值都只有1个
Func<int> f = () => { return 100; };
int result = f();
Console.WriteLine(result);
//Func<int, int, int>最后一个参数是返回值类型,这里参数是2个,返回值1个,一共3个
Func<int, int, int> f1 = (x, y) => { return x + y; };
int result1 = f1(3, 50);
Console.WriteLine(result1);
Console.ReadKey();
}
static void M1(string msg)
{
Console.WriteLine(msg);
}
}
}
事件,也是委托,有点特殊的委托
using System;
using System.Threading;
namespace _04_事件
{
#region 用委托处理播放器
//class Program
//{
// static void Main(string[] args)
// {
// MusicPlayer mp3 = new MusicPlayer();
// mp3.AfterStartedPlay = () =>
// {
// Console.WriteLine("加载歌词");
// };
// mp3.BeforeStopPlay = () =>
// {
// Console.WriteLine("删除歌词");
// };
// mp3.StartPlay();
// mp3.StopPlay();
// //如果把上两行注释掉,执行下面两行,也能执行,但是逻辑不对,因为没有播放就加载歌词了,因为委托必须是public,所以外界随意访问
// //mp3.BeforeStopPlay();
// //mp3.AfterStartedPlay();
// //也可以对委托赋值,如下面两行,这样就失去意义
// //mp3.AfterStartedPlay = null;
// //mp3.BeforeStopPlay = null;
// //以上两点,既可以随意访问,又可以随意赋值,不符合逻辑
// Console.ReadKey();
// }
//}
//public class MusicPlayer
//{
// //做几个事件
// //音乐播放后显示歌词
// public Action AfterStartedPlay;
// //音乐停止前关闭歌词
// public Action BeforeStopPlay;
// private void PlayMusic()
// {
// Console.WriteLine("开始播放音乐!");
// }
// public void StartPlay()
// {
// PlayMusic();
// //音乐播放之后触发该事件
// if(AfterStartedPlay!=null)
// {
// AfterStartedPlay();
// }
// Thread.Sleep(2000);
// }
// public void StopPlay()
// {
// //音乐结束之前触发该事件
// if (BeforeStopPlay != null)
// {
// BeforeStopPlay();
// }
// Console.WriteLine("播放结束!");
// }
//}
#endregion
#region 用事件event处理播放器
class Program
{
static void Main(string[] args)
{
MusicPlayer mp3 = new MusicPlayer();
mp3.AfterStartedPlay += new Action(Mp3_AfterStartedPlay);
mp3.BeforeStopPlay += new Action(Mp3_BeforeStopPlay);
mp3.StartPlay();
mp3.StopPlay();
//事件不能再外部调用,所以下列调用无效
//事件只能在定义时间的类的内部来触发
//mp3.AfterStartedPlay();
Console.ReadKey();
}
private static void Mp3_AfterStartedPlay()
{
Console.WriteLine("加载歌词");
}
private static void Mp3_BeforeStopPlay()
{
Console.WriteLine("删除歌词");
}
}
public class MusicPlayer
{
//做几个事件
//音乐播放后显示歌词,加了event
public event Action AfterStartedPlay;
//音乐停止前关闭歌词
public event Action BeforeStopPlay;
private void PlayMusic()
{
Console.WriteLine("开始播放音乐!");
}
public void StartPlay()
{
PlayMusic();
//音乐播放之后触发该事件
if (AfterStartedPlay != null)
{
AfterStartedPlay();
}
Thread.Sleep(2000);
}
public void StopPlay()
{
//音乐结束之前触发该事件
if (BeforeStopPlay != null)
{
BeforeStopPlay();
}
Console.WriteLine("播放结束!");
}
}
#endregion
}