看看这个例子,能不能:想进行加法运算的时候就加法,想乘法的时候就乘法?
static void AICaculate(int a, int b) { Console.WriteLine("I'm AI caculator, let me try:"); Add(a, b); //Multiple(a, b); } static void Add(int a, int b) { Console.WriteLine($"it's so easy, {a}+{b}={a + b}"); } static void Multiple(int a, int b) { Console.WriteLine($"I can I can, {a}*{b}={a * b}"); }
思路:通过AICaculate()的参数进行控制,
static void AICaculate(int a, int b, string opt) { Console.WriteLine("I'm AI caculator, let me try:"); if (opt == "Add") //add { Add(a, b); } else { Multiple(a, b); } }
程序员应该对使用string类型进行判断比较保持警惕:
enum Opt //应当引入enum { Add, Multiple, //Minus }
然后,使用switch...case:
switch (opt) { case Opt.Add: Add(a, b); break; case Opt.Multiple: Multiple(a, b); break; default: //复习:为什么要抛出异常 throw new ArgumentException(""); }一个可行的办法,是将方法本身(而不是方法的结果)作为参数传递过来:
public static void Main(string[] args) { AICaculate(Add, /* 将方法直接传入 */ 3, 5); } static void AICaculate(Action<int, int> calculate, /*这个参数是什么鬼?*/ int a, int b) { Console.WriteLine("I'm AI caculator, let me try:"); calculate(a, b); }
F12查看 Action<int, int> 的定义,我们发现:
public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);注意关键字delegate(委托),而不是通常的class或struct。
什么是委托?
//像声明一个类一样声明一个委托 //但定义了这个委托的返回void类型,接受两个int类型的参数 delegate void Calculate(int a, int b);
//把方法(不是方法的返回值)直接赋值给一个Calculate委托变量 Calculate ai = Add; //类似于调用Add()方法一样调用delegateAdd ai(3, 7);
另外,委托类型的变量可以和普通变量一样的:
而且,为了便于Lambda表达式的传递,.NET为我们预置了两种委托:
Func和Action为我们提供了最多16个参数,怎么都够用了!^_^
@想一想@:如果说16个参数还不够怎么办?
而且这两种委托都是泛型的,所以我们基本上都不再自己声明委托了。
public delegate TResult Func<in T, out TResult>(T arg); public delegate void Action<in T>(T obj);
委托是事件的基础,事件又对委托进行了封装……
在Winform和以前的WebForm中,事件被大量使用,是必须掌握的知识(但MVC不是事件驱动的),一个完整的事件流程包括:
public class Button { //定义事件,用于发布 public event EventHandler OnClick; //注意:EventHnadler是一个委托 public void click() { if (OnClick != null) { OnClick(this, new EventArgs()); } } }
//实例化一个发布了OnClick事件的button Button btn = new Button(); //事件被btn_click订阅,即:当这个btn被click时调用btn_click()方法 btn.OnClick += btn_click;
private static void btn_click(object sender, EventArgs e) { Console.WriteLine("点我干啥呢?"); }
//事件被触发 btn.click();
注意:event和delegate都可以被多次订阅(+=)/退订(-=),演示:略