C#委托的总结

一、委托的基本形式

	// 定义委托
    public delegate void Dlg(string name);

    public partial class FormTest : Form
    {
        public FormTest()
        {
            InitializeComponent();
        }

        private void FormTest_Load(object sender, EventArgs e)
        {
            Person zhangsan = new Person();
            // 使用委托
            zhangsan.PersonSay(GoToWorld, "ZhangSan");
        }

		// 委托指向的方法
        public void GoToWorld(string name)
        {
            MessageBox.Show(name + " Say Hello World");
        }
    }

    public class Person
    {
    	// 将委托作为参数
        public void PersonSay(Dlg delEat, string name)
        {
            delEat(name);
        }
    }

二、泛型委托和泛型方法

// 定义泛型委托
public delegate void Dlg<T>(T t);

public partial class FormTest : Form
{
    public FormTest()
    {
        InitializeComponent();
    }

    private void FormTest_Load(object sender, EventArgs e)
    {
    	// 使用泛型委托
        Person zhangsan = new Person();
        zhangsan.PersonSay(GoToWorld, "ZhangSan");
    }

	// 被泛型委托指向的泛型方法
    public void GoToWorld<T>(T name)
    {
        MessageBox.Show(name + " Say Hello World");
    }
}

public class Person
{
	// 泛型委托作为参数被调用
    public void PersonSay<T>(Dlg<T> delEat, T name)
    {
        delEat(name);
    }
}

三、返回值为泛型变量的泛型委托

	// 定义泛型委托,泛型错误
    public delegate T Dlg<T>(T t);

    public partial class FormTest : Form
    {
        public FormTest()
        {
            InitializeComponent();
        }

        private void FormTest_Load(object sender, EventArgs e)
        {
            // 使用泛型委托
            Person zhangsan = new Person();
            string name = "ZhangSan";
            string rtn = zhangsan.PersonSay(GoToWorld, name);
            MessageBox.Show(rtn );
        }
		
		// 被泛型委托指向的方法,返回参数为泛型委托
        public T GoToWorld<T>(T name)
        {            
        	// default(T)表示T的默认值,比如int默认值是0
        	T t = default(T);
            return name;
        }
    }

    public class Person
    {
    	// 泛型委托作为参数被调用,返回泛型变量
        public T PersonSay<T>(Dlg<T> delEat, T name)
        {
            T s =  delEat(name);
            return s;
        }
    }

四、匿名方法作形参

	public delegate string Dlg();
	
	public partial class FormTest : Form
	{
	    public FormTest()
	    {
	        InitializeComponent();
	    }
	
	    private void FormTest_Load(object sender, EventArgs e)
	    {
	        Person zhangsan = new Person();
	        // 匿名委托,不用传一个方法给委托实参,直接使用匿名委托
	        string rtn = zhangsan.PersonSay(delegate() {
	            return "Hello";
	        }, " world");
	        MessageBox.Show(rtn);
	    }
	}
	
	public class Person
	{
	    public string PersonSay(Dlg delEat, string msg)
	    {
	        return delEat() + msg;
	    }
	}

带参数的匿名方法

    public delegate string Dlg(string msg);

    public partial class FormTest : Form
    {
        public FormTest()
        {
            InitializeComponent();
        }

        private void FormTest_Load(object sender, EventArgs e)
        {
            Person zhangsan = new Person();
            // 匿名委托,不用传一个方法给委托实参,直接使用匿名委托
            string rtn = zhangsan.PersonSay(delegate(string msg) {
                return msg;
            }, "Hello World");
            MessageBox.Show(rtn);
        }
    } 

    public class Person
    {
        public string PersonSay(Dlg delEat, string msg)
        {
            return delEat(msg);
        }
    }

五、Lambda表达式

Lambda表达式实质就是一个匿名的委托,可以作为委托形式的实参传递给方法。
带参数的Lambda表达式:

    public delegate string Dlg(string msg);

    public partial class FormTest : Form
    {
        public FormTest()
        {
            InitializeComponent();
        }

        private void FormTest_Load(object sender, EventArgs e)
        {
            Person zhangsan = new Person();
            // 匿名委托,不用传一个方法给委托实参,直接使用匿名委托
            string rtn = zhangsan.PersonSay((msg) =>{
                return msg;
            }, "Hello World");
            MessageBox.Show(rtn);
        }
    } 

    public class Person
    {
        public string PersonSay(Dlg delEat, string msg)
        {
            return delEat(msg);
        }
    }

进一步精简Lambda表达式

    public delegate string Dlg(string msg);

    public partial class FormTest : Form
    {
        public FormTest()
        {
            InitializeComponent();
        }

        private void FormTest_Load(object sender, EventArgs e)
        {
            Person zhangsan = new Person();
            // 匿名委托,不用传一个方法给委托实参,直接使用匿名委托
            string rtn = zhangsan.PersonSay((msg) => msg, "Hello World");
            MessageBox.Show(rtn);
        }
    } 

    public class Person
    {
        public string PersonSay(Dlg delEat, string msg)
        {
            return delEat(msg);
        }
    }

六、多播委托

将委托设置为属性,然后可以传入多个委托指向的方法,类似事件。

	//定义委托
	public delegate void Dlg(string msg);

    public partial class FormTest : Form
    {
        public FormTest()
        {
            InitializeComponent();
        }

        private void FormTest_Load(object sender, EventArgs e)
        {
            Person zhangsan = new Person();
            // 利用+=和-=符号增加或减少指向的方法
            zhangsan.OnSay += SayHello;
            zhangsan.OnSay += SayHi;
            zhangsan.OnSay += SayGo;

            zhangsan.OnSay -= SayHi;

            zhangsan.PersonSay();
			
			// 多播委托可以直接调用委托属性,但事件不行
			zhangsan.OnSay();

        }

        void SayHello(string name)
        {
            MessageBox.Show(name + " say hello");
        }

        void SayHi(string name)
        {
            MessageBox.Show(name + " say hi");
        }

        void SayGo(string name)
        {
            MessageBox.Show(name + " say go");
        }
    }

    public class Person
    {
    	// 委托设置为属性,可以接收多个指向的方法
        public Dlg OnSay { get; set; }

        public void PersonSay( )
        {
            string name = "zhang san";
            // 调用委托属性指向的方法集合
            OnSay(name);
        }
    }

七、事件

将多播委托的委托设置改为event,然后可以传入多个被调用的方法,极其类似多播委托。事件和多播委托的区别,多播委托可以直接调用委托属性,然后执行多个被指向的方法;但事件不行,会出现语法错误。事件是委托的封装,让其在外部不能被随意调用,增加安全性。

	// 定义用于事件的委托
    public delegate void Dlg(string msg);

    public partial class FormTest : Form
    {
        public FormTest()
        {
            InitializeComponent();
        }

        private void FormTest_Load(object sender, EventArgs e)
        {
            Person zhangsan = new Person();
            zhangsan.OnSay += SayHello; // 为事件添加指向的方法
            zhangsan.OnSay += SayHi;
            zhangsan.OnSay += SayGo;

            zhangsan.OnSay -= SayHi;

            zhangsan.PersonSay();
			// 多播委托可以直接调用委托属性,但事件不行,语法错误
			// zhangsan.OnSay();
        }
		
		// 事件指向的方法
        void SayHello(string name)
        {
            MessageBox.Show(name + " say hello");
        }

        void SayHi(string name)
        {
            MessageBox.Show(name + " say hi");
        }

        void SayGo(string name)
        {
            MessageBox.Show(name + " say go");
        }
    }

    public class Person
    {
    	// 将多播委托里面的属性改为事件event
        public event Dlg OnSay;

        public void PersonSay( )
        {
            string name = "zhang san";
            OnSay(name);
        }
    }

八、内置委托

使用内置委托后,不再需要声明委托了,可以直接使用;

  1. Action<>是无返回值的泛型委托;Action<>里面可以放置16个参数
Action action = deletegate(){
	Console.WriteLine("Hello");
};

action();
  1. 异步委托的等待
        private void button1_Click(object sender, EventArgs e)
        {
            Action action = delegate ()
            {
                Console.WriteLine("action");
            };

            IAsyncResult result = null;
            // 运行10次异步委托
            for(int i = 0; i < 10; i++)
            {
                // 异步委托里面的o就是result实例
                result = action.BeginInvoke(new AsyncCallback((o) =>
                {
                    Console.WriteLine("hello");
                    // o.AsyncState就是传值进来的"stateValue"字符串
                    Console.WriteLine(o.AsyncState);
                }), "stateValue");
            }

            // WaitOne阻塞主线程,等待异步委托,当有一个异步委托执行,则会返回true值,执行主线程
            bool waitWatch = result.AsyncWaitHandle.WaitOne();
        }
  1. Func是有返回值的泛型委托
    使用方法同Action<>,但Func<>有返回值,Func<>的参数里面,最后一个参数是返回值
    public partial class FormTest1 : Form
    {
        public FormTest1()
        {
            InitializeComponent();
        }

        private void FormTest_Load(object sender, EventArgs e)
        {
            Person zhangsan = new Person();

            zhangsan.PersonEat(Eat);
			string str = zhangsan.PersonRun(Run);
        }

        void Eat(string name, int i)
        {
            MessageBox.Show(name + "在吃第" + i + "顿饭!");
        }
        
        string Run(string name)
        {
            return name + "在跑步!";
        }
    }

    public class Person
    {
        public void PersonEat(Action<string,int> eat)
        {
            string name = "zhang san";
            int i = 9;
            eat(name, i);
        }
		
		 pulic string PersonRun(Func<string,string> run)
        {
        	string name = "zhang san";
            return run(name);
        }
    }
  1. Predicate<>是返回bool类型的委托
    使用方法同Action<>

你可能感兴趣的:(C#语言,c#,开发语言,ui)