1.委托
1.委托使得一个方法可以作为另一个方法的参数进行传递
2.多播委托
public delegate int Expression(int a, int b);
class Program1
{
static void Main(string[] args)
{
//1.将方法作为参数传递
Calculate(GetAdd, 25, 10);
//2.多播委托
Expression e;
e = Add;
e += Divide;
e(1,2);
}
static int Add(int a, int b)
{
return a + b;
}
static int Divide(int a, int b)
{
return a / b;
}
static int subtract(int a, int b)
{
return a - b;
}
static int multiply(int a, int b)
{
return a * b;
}
static int GetAdd(int a, int b)
{
return a + b;
}
static void Calculate(Expression ex, int a, int b)
{
Console.WriteLine(ex(a, b) + "\n");
}
}
https://www.cnblogs.com/wangjiming/p/8300103.html
https://www.cnblogs.com/TJessica/p/6690120.html
https://blog.youkuaiyun.com/u014224380/article/details/82996533
https://blog.youkuaiyun.com/goodshot/article/details/6157529
2.事件
个人理解:
1.多播委托中
//2.多播委托
Expression e;
e = Add;
e += Divide;
e = subtract;
e(1,2);
此时e只会执行subtract,委托链z中断
2.类的外部要给委托赋值和多播委托,则委托定义为public,外部就可以调用委托的实例( a.d(1) ),而一些情况下外部不应该直接调用
class A
{
public delegate void de(int a);
public de d;
}
void fun()
{
A a = new A();
//a.d =new A.de(add);
a.d =add;
a.d(1);
}
void add(int i)
{
}
以上两点引出了事件的概念
事件只需在委托前加event即可:
public event de d;
事件可以理解成一个委托的属性,通过对委托实例的封装来对委托实例的访问进行一些限制
class T
{
private int a;
public int A{ get; set; }
}
事件通过IL得出的代码类似
public event AssembleIphoneHandler VerdorToAssembleIphone;
=>
private AssembleIphoneHandler VerdorToAssembleIphone;
public void add_VerdorToAssembleIphone(AssembleIphoneHandler 'value') { }
public void remove_VerdorToAssembleIphone(AssembleIphoneHandler 'value') { }
即事件封装了委托的实例,针对上面两点:
1.event只能+= 或者-= ,在外部不能直接赋值
2.事件只能在内部invoke,外部无法直接调用
- 在定义事件的类内部,不管你声明它是public还是protected,它总是private的;也就是说在在定义事件的类外部不能对事件进行调用
- 在定义事件的类外部,添加"+=“和移除”-=“委托实例的访问限定符与声明事件时使用的访问符相同也就是说,如果事件声明为private或这protect,那么定义事件的类外部也不能对事件进行”+=“和”-="操作
delegate void MyEvent(object sender, CustomEventArgs e);
public delegate void MyDelegate1(string name);
class PersonManager
{
public event MyEvent Myevent;
public MyDelegate1 delegate1;
//执行事件
public void Execute(CustomEventArgs e)
{
MyEvent handler = Myevent;
if (handler != null)
{
handler(this, e);
}
}
}
class Program
{
public static void Mainq()
{
PersonManager personManager = new PersonManager();
//绑定事件处理方法
personManager.Myevent += GetNameEv;
personManager.Execute(new CustomEventArgs("a","b","c")); //加了event不能直接在外部调用,只能在内部调用
personManager.delegate1 += GetName;
personManager.delegate1 += GetOld;
personManager.delegate1("ssss"); //没加event可在外部直接调用
}
public static void GetNameEv(object sender, CustomEventArgs e)
{
}
public static void GetName(string name)
{
MessageBox.Show("My name is " + name);
}
public static void GetOld(string age)
{
MessageBox.Show("My age is " + age);
}
}
Tips:
委托和事件的异步执行(多线程的一种)
class A
{
public delegate void de(int a);
public de d;
//public event de d;
}
void fun()
{
A a = new A();
//a.d =new A.de(add);
a.d =add;
a.d(1);
//异步执行,可注册完成后的回调事件
//IAsyncResult asyncResult = a.d.BeginInvoke(2, null, null);
}
void add(int i)
{
}
https://www.cnblogs.com/wilber2013/p/4285033.html
3.EventHandler
class CustomEventArgs:EventArgs
{
public string From { get; }
public string To { get; }
public string Content { get; set; }
public CustomEventArgs(string from, string to, string content)
{
From = from;
To = to;
Content = content;
}
}
class MailManager
{
//EventHandler<CustomEventArgs>是一个泛型委托,相当于说内部自动写了一个委托,也可以自己写委托实现,见上面PersonManager不带泛型的
//public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
public event EventHandler<CustomEventArgs> newMail;
public void ReceiveNewMail(string from, string to, string content)
{
//DoSomething…………
//触发事件
CustomEventArgs e = new CustomEventArgs(from, to, content);
OnNewMail(e);
}
//使用虚方法,让子类可以重写
protected virtual void OnNewMail(CustomEventArgs e)
{
//newMail?.Invoke(this,e);
// 定义一个局部变量,已防止最后一个订阅者刚好在检查null后取消订阅
EventHandler<CustomEventArgs> handler = newMail;
if (handler != null)
{
// 格式化事件消息中 的字符串
e.Content += String.Format(" at {0}", DateTime.Now.ToString());
handler(this, e);
}
}
}
class MailReader
{
public MailReader(MailManager mm)
{
//注册事件
mm.newMail += ReadMail;
}
// 实现回调函数。 在事件发生后,执行什么样的操作
private void ReadMail(object sender, CustomEventArgs e)
{
Console.WriteLine(string.Format("fax receive,from:{0} to:{1} content is:{2}", e.From, e.To, e.Content));
}
}
class Class1
{
static void Main(string[] args)
{
MailManager pub = new MailManager();
MailReader sub1 = new MailReader(pub);
MailReader sub2 = new MailReader(pub);
// 调用这个方法来产生事件
pub.ReceiveNewMail("a","b","c");
}
}
https://www.cnblogs.com/zhaoshujie/p/11042292.html
//这里定义了一个水箱类
public class 水箱
{
//这是水箱的放水操作
public void 放水() { }
//这是水箱的属性
public double 体积;
//这是水箱空的事件
public event EventHandler 水箱空;
}
//这里定义了一个加水器类
public class 加水器
{
public void 加水(Object sender, EventArgs e)
{
//对需要加水的水箱进行加水操作
}
}
public class User
{
public User()
{
//实例化水箱类
水箱1 = new 水箱();
//实例化加水器类
加水器1 = new 加水器();
//加水器注册水箱空事件
水箱1.水箱空 += new EventHandler(加水器1.加水);
}
private 加水器 加水器1;
private 水箱 水箱1;
}
EventHandler、EventHandler和delegate对比
delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
public event EventHandler<CustomEventArgs> newMail;
delegate void MyEvent(object sender, CustomEventArgs e);
public event MyEvent Myevent;
public event EventHandler 水箱空;
EventHandler跟Action
http://www.paulrohde.com/events-eventhandler-or-action/