wangdeshui 发表于 2013-2-4 23:16:19

C#拾遗系列(1):委托

一、委托概述
委托具有以下特点:
   
[*]    委托类似于 C++ 函数指针,但它们是类型安全的。
   
[*]    委托允许将方法作为参数进行传递。
   
[*]    委托可用于定义回调方法。
   
[*]    委托可以链接在一起;例如,可以对一个事件调用多个方法。
   
[*]    方法不必与委托签名完全匹配。(委托中的协变和逆变)
   
[*]    C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递,以代替单独定义的方法。C# 3.0 引入了 Lambda 表达式,利用它们可以更简练地编写内联代码块。匿名方法和 Lambda 表达式(在某些上下文中)都可编译为委托类型。这些功能统称为匿名函数
二、委托申明和使用示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
//Description: 委托三种声明方式.net1.0到.net3.0
 
namespace NetTest

    public class TestDelegateNet1To3
    {
        #region 不带返回值的委托
        delegate void TestDelegate(string s);
        public void TestAllDelegate()
        {
            //.net 1.0
            TestDelegate en = new TestDelegate(M);
            en("jack");
            TestDelegate china = China;
            china("wangdeshui");
 
            //.net 2.0
            TestDelegate delegateNet2 = delegate(string s) { Console.Out.WriteLine(s + ":这是一个2.0的方式"); };
            delegateNet2("2.0 delegate declare");
 
            //.net 3.0
            TestDelegate delegateNet3 = (string s) => { Console.Out.WriteLine(s + ":这是3.0的方式"); };
            delegateNet3("3.0 delegate declare");
 
            TestReturn(); 
 
            Func<int, bool> d = (n) => { return n > 10 ? true : false; };
            Console.Out.WriteLine("func<int, bool>:" + d(20));
 
 
        }
 
        void M(string s)
        {
            Console.Out.WriteLine(s + ":Good Morning");
        }
 
        void China(string s)
        {
            Console.Out.WriteLine(s + ":早上好");
        }
        #endregion
 
 
        #region 带返回值的委托测试
 
        delegate bool TestDelegateReturn(int i);
        void TestReturn()
        {
            TestDelegateReturn Net10 = new TestDelegateReturn(IsBig);
            bool i = Net10(11);
            Console.Out.WriteLine("Net10:" + i);
 
            TestDelegateReturn Net20 = delegate(int j)
            {
                return (j > 10 ? true : false);
 
            };
 
            bool test20 = Net20(5);
            Console.Out.WriteLine("Net20:" + test20);
 
            TestDelegateReturn Net30 = (int k) => { return (k > 10 ? true : false); };
            bool test30 = Net30(50);
            Console.Out.WriteLine("Net30:" + test30);
 
        }
 
        bool IsBig(int i)
        {
            return i > 10 ? true : false;
 
        }
 
        #endregion
    }
}
 
三、多播委托
<blockquote>调用委托时,它可以调用多个方法。这称为多路广播。若要向委托的方法列表(调用列表)中添加额外的方法,只需使用加法运算符或加法赋值运算符(“+”或“+=”)添加两个委托。
注意:
作为委托参数传递的方法必须与委托声明具有相同的签名。
委托实例可以封装静态或实例方法。
尽管委托可以使用 out 参数,但建议您不要将其用于多路广播事件委托,因为您无法知道哪个委托将被调用。
多播委托传递值类型时,对参数的修改不会传到下一个
多播委托传递引用类型时,对引用参数的修改会传到下一个
示例:
<div style="font-size: 10pt; color: black; font-family: lucida console;">public class TestMultiCastDelegate
    {
        public delegate void Del(string message);
        delegate void DelRef(Person p);
        void MethodA(string s)
        {
            Console.Out.WriteLine("Method A:"+s);
        }
 
        void MethodB(string s)
        {
            s = "good";
            Console.Out.WriteLine("Method B:" + s);
        }
 
        void MethodC(string s)
        {
            Console.Out.WriteLine("Method C:" + s);
        }
 
        /*
        多播委托传递值类型时,对参数的修改不会传到下一个
        多播委托传递引用类型时,对引用参数的修改会传到下一个
        *
        * */
 
        public void Test()
        {
            //多播委托
            Del d1 = MethodA;
            Del d2 = MethodB;
            Del d3=MethodC;
            Del AllDelegateMethod = d1 + d2;
            AllDelegateMethod += d3;
            AllDelegateMethod("Jack");
            /*
            output:
            ConsoleA: Jack
            ConsoleB: Jack
            ConsoleC:Jack           
            */
            Console.Out.WriteLine("---------------------");
            AllDelegateMethod -= d3;
            AllDelegateMethod("wangds");
 
 
            //测试引用类型
            DelRef dref1 = MethodRefA;
            DelRef dref2 = MethodRefB;
            DelRef Alldref = dref1 + dref2;
            Person p = new Person { Address = "USA", Name = "America" };
            Alldref(p);
        }
 
 
        //内嵌类
 
        class Person
        {
            public string Name { get; set; }
            public string Address { get;  set; }
 
        }
 
        void MethodRefA(Person p)
        {
            Console.Out.WriteLine(p.Name + "," + p.Address);
            Console.Out.WriteLine("----------MethodRefA---------");
            p.Name = "Jack";
            p.Address = "China";
 
            Console.Out.WriteLine(p.Name + "," + p.Address);
            Console.Out.WriteLine("----------MethodRefA---------");
        }
 
        void MethodRefB(Person p)
        {
            Console.Out.WriteLine("--------MethodRefB----------");
            Console.Out.WriteLine(p.Name + "," + p.Address);
            Console.Out.WriteLine("--------MethodRefB----------");
        }
    }
页: [1]
查看完整版本: C#拾遗系列(1):委托