C#委托的介绍(delegate、Action、Func、predicate)

委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递。事件是一种特殊的委托。
1.委托的声明
(1). delegate
delegate我们常用到的一种声明
Delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型。
例:public delegate int MethodtDelegate(int x, int y);表示有两个参数,并返回int型。
(2). Action
Action是无返回值的泛型委托。
Action 表示无参,无返回值的委托
Action<int,string> 表示有传入参数int,string无返回值的委托
  Action<int,string,bool> 表示有传入参数int,string,bool无返回值的委托
 Action<int,int,int,int> 表示有传入4个int型参数,无返回值的委托
Action至少0个参数,至多16个参数,无返回值。
例:
public void Test<T>(Action<T> action,T p) { action(p); }
 (3). Func
Func是有返回值的泛型委托
Func<int> 表示无参,返回值为int的委托
Func<object,string,int> 表示传入参数为object, string 返回值为int的委托
Func<object,string,int> 表示传入参数为object, string 返回值为int的委托
Func<T1,T2,,T3,int> 表示传入参数为T1,T2,,T3(泛型)返回值为int的委托
Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可void
例:
public int Test<T1,T2>(Func<T1,T2,int>func,T1 a,T2 b) { return func(a, b); }
 (4) .predicate
predicate 是返回bool型的泛型委托
predicate<int> 表示传入参数为int 返回bool的委托
Predicate有且只有一个参数,返回值固定为bool
例:public delegate bool Predicate<T> (T obj)
2.委托的使用
(1).Delegate的使用
(2).Action的使用
可以使用 Action<T1, T2, T3, T4> 委托以参数形式传递方法,而不用显式声明自定义的委托。 封装的方法必须与此委托定义的方法签名相对应。 也就是说,封装的方法必须具有四个均通过值传递给它的参数,并且不能返回值。 (在 C# 中,该方法必须返回 void)通常,这种方法用于执行某个操作。
(3).Func的使用
(4). predicate的使用
泛型委托:表示定义一组条件并确定指定对象是否符合这些条件的方法。此委托由 Array 和 List 类的几种方法使用,用于在集合中搜索元素。
使用带有 Array.Find 方法的 Predicate 委托搜索 Point 结构的数组。如果 X 和 Y 字段的乘积大于 100,000,此委托表示的方法 ProductGT10 将返回 true。Find 方法为数组的每个元素调用此委托,在符合测试条件的第一个点处停止。
3.委托的清空
(1).在类中申明清空委托方法,依次循环去除委托引用。
方法如下:
(2).如果在类中没有申明清空委托的方法,我们可以利用GetInvocationList查询出委托引用,然后进行去除。
方法如下:
4.委托的特点
委托类似于 C++ 函数指针,但它们是类型安全的。   委托允许将方法作为参数进行传递。   委托可用于定义回调方法。   委托可以链接在一起;例如,可以对一个事件调用多个方法。   方法不必与委托签名完全匹配。
5.总结:
Delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型
Func可以接受0个至16个传入参数,必须具有返回值
Action可以接受0个至16个传入参数,无返回值
Predicate只能接受一个传入参数,返回值为bool类型
详细参考:http://www.fengfly.com/plus/view-209140-1.html
http://www.cnblogs.com/foolishfox/archive/2010/09/16/1827964.html
附:
Event & Delegate
An Event declaration adds a layer of abstraction and protection on the delegate instance. This protection prevents clients of the delegate from resetting the delegate and its invocation list and only allows adding or removing targets from the invocation list.
Delegate对应到设计模式中的代理模式,而event则对应到观察者模式。
使用delegate的目的是在方法中传递方法指针。通过声明delegate的方法签名,可以在运行时在符合delegate方法签名的方法中选择要执行的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ModernLanguageConstructs { class Program { // Part 1 - Explicit declaration of a delegate //(helps a compiler ensure type safety) public delegate double delegateConvertTemperature(double sourceTemp); // A sample class to play with class TemperatureConverterImp { // Part 2 - Will be attached to a delegate later in the code public double ConvertToFahrenheit(double celsius) { return (celsius * 9.0/5.0) + 32.0; } // Part 3 - Will be attached to a delegate later in the code public double ConvertToCelsius(double fahrenheit) { return (fahrenheit - 32.0) * 5.0 / 9.0; } } static void Main(string[] args) { // Part 4 - Instantiate the main object TemperatureConverterImp obj = new TemperatureConverterImp(); // Part 5 - Intantiate delegate #1 delegateConvertTemperature delConvertToFahrenheit = new delegateConvertTemperature(obj.ConvertToFahrenheit); // Part 6 - Intantiate delegate #2 delegateConvertTemperature delConvertToCelsius = new delegateConvertTemperature(obj.ConvertToCelsius); // Use delegates to accomplish work // Part 7 - delegate #1 double celsius = 0.0; double fahrenheit = delConvertToFahrenheit(celsius); string msg1 = string.Format("Celsius = {0}, Fahrenheit = {1}", celsius, fahrenheit); Console.WriteLine(msg1); // Part 8 - delegate #2 fahrenheit = 212.0; celsius = delConvertToCelsius(fahrenheit); string msg2 = string.Format("Celsius = {0}, Fahrenheit = {1}", celsius, fahrenheit); Console.WriteLine(msg2); } } }
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class SampleEventArgs { public SampleEventArgs(string s) { Text = s; } public String Text {get; private set;} // readonly } public class Publisher { // Declare the delegate (if using non-generic pattern). public delegate void SampleEventHandler(object sender, SampleEventArgs e); // Declare the event. public event SampleEventHandler SampleEvent; // Wrap the event in a protected virtual method // to enable derived classes to raise the event. protected virtual void RaiseSampleEvent() { // Raise the event by using the () operator. if (SampleEvent != null) SampleEvent(this, new SampleEventArgs("Hello")); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ModernLanguageConstructs { class Program { static void Main(string[] args) { // Part 1 - First action that takes an int and converts it to hex Action<int> displayHex = delegate(int intValue) { Console.WriteLine(intValue.ToString("X")); }; // Part 2 - Second action that takes a hex string and // converts it to an int Action<string> displayInteger = delegate(string hexValue) { Console.WriteLine(int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber)); }; // Part 3 - exercise Action methods displayHex(16); displayInteger("10"); } } }
If course, this protection layer also prevents "clients" (code outside the defining class/struct) from invokingthe delegate, and from obtaining in any way the delegate object "behind" the event.
原文地址:https://www.cnblogs.com/kdp0213/p/8555942.html