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]