配色设计网站推荐,广告公司宣传册,浙江建设信息港三类人员成绩查询,wordpress计数器委托#xff08;delegate#xff09;特别用于实现事件和回调方法。所有的委托#xff08;Delegate#xff09;都派生自 System.Delegate 类。事件是一种特殊的多播委托#xff0c;仅可以从声明事件的类或结构中对其进行调用。类或对象可以通过事件向其他类或对象通知发生的…委托delegate特别用于实现事件和回调方法。所有的委托Delegate都派生自 System.Delegate 类。事件是一种特殊的多播委托仅可以从声明事件的类或结构中对其进行调用。类或对象可以通过事件向其他类或对象通知发生的相关事情。本文主要介绍C#中委托和事件的使用总结。
1、委托的简单使用
一个委托类型定义了该类型的实例能调用的一类方法这些方法含有同样的返回类型和同样参数类型和个数相同。委托和接口一样可以定义在类的外部。
例如
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApplication
{delegate int Calculator(int x);class Program{static int Double(int x) { return x * 2; }static void Main(string[] args){Calculator c Double;int result c(2);Console.Write(result);Console.ReadKey();}}
}
2、用委托实现插件式编程 委托是一个能把方法作为参数传递的对象通过这个可以来实现插件式编程。
例如
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApplication
{delegate int Calculator(int x);class Program{static int Double(int x) { return x * 2; }static void Main(string[] args){int[] values { 1, 2, 3, 4 };Utility.Calculate(values, Double);//使用方法Utility.Calculate(values, x x * 2);//使用Lambda表达式foreach (int i in values)Console.Write(i ); // 2 4 6 8Console.ReadKey();}}class Utility{public static void Calculate(int[] values, Calculator c){for (int i 0; i values.Length; i)values[i] c(values[i]);}}
}
3、多播委托
多播委托是指在一个委托中注册多个方法在注册方法时可以在委托中使用加号运算符或者减号运算符来实现添加或撤销方法。创建一个委托被调用时要调用的方法的调用列表。这被称为委托的 多播multicasting也叫组播。
例如
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApplication
{public delegate void ProgressReporter(int percentComplete);public class Utility{public static void Match(ProgressReporter p){if (p ! null){for (int i 0; i 10; i){p(i * 10);System.Threading.Thread.Sleep(100);}}}}class Program{static void Main(string[] args){ProgressReporter p WriteProgressToConsole;p WriteProgressToFile;Utility.Match(p);Console.WriteLine(Done.);Console.ReadKey();}static void WriteProgressToConsole(int percentComplete){Console.WriteLine(percentComplete %);}static void WriteProgressToFile(int percentComplete){System.IO.File.AppendAllText(progress.txt, percentComplete %);}}
}
4、静态方法和实例方法对于委托的区别
一个类的实例的方法被赋给一个委托对象时在上下文中不仅要维护这个方法还要维护这个方法所在的实例。System.Delegate 类的Target属性指向的就是这个实例。
例如
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace BRG
{public delegate void ProgressReporter(int percentComplete);class Program{static void Main(string[] args){X x new X();ProgressReporter p x.InstanceProgress;p(1);Console.WriteLine(p.Target x); // TrueConsole.WriteLine(p.Method); // Void InstanceProgress(Int32) }static void WriteProgressToConsole(int percentComplete){Console.WriteLine(percentComplete %);}static void WriteProgressToFile(int percentComplete){System.IO.File.AppendAllText(progress.txt, percentComplete %);}}class X{public void InstanceProgress(int percentComplete){// do something }}
}
但对于静态方法System.Delegate 类的Target属性是Null所以将静态方法赋值给委托时性能更好。
5、泛型委托
泛型委托和泛型的用法一样就是含有泛型参数的委托。
例如
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApplication
{public delegate T CalculatorT(T arg);class Program{static int Double(int x) { return x * 2; }static void Main(string[] args){int[] values { 1, 2, 3, 4 };Utility.Calculate(values, Double);foreach (int i in values)Console.Write(i ); // 2 4 6 8Console.ReadKey();}}class Utility{public static void CalculateT(T[] values, CalculatorT c){for (int i 0; i values.Length; i)values[i] c(values[i]);}}
}
6、事件的基本使用
声明一个事件很简单只需在声明一个委托对象时加上event关键字就行。
例如
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Example_EventTest
{class Judgment{//定义一个委托public delegate void delegateRun();//定义一个事件public event delegateRun eventRun;//引发事件的方法public void Begin(){eventRun();//被引发的事件}}class RunSports{//定义事件处理方法public void Run(){Console.WriteLine(开始运行方法);}}class Program{static void Main(string[] args){RunSports runsport new RunSports();//实例化事件发布者Judgment judgment new Judgment();//实例化事件订阅者//订阅事件judgment.eventRunnew Judgment.delegateRun(runsport.Run);//引发事件judgment.Begin();Console.ReadKey();}}
}
注意事件有一系列规则和约束用以保证程序的安全可控事件只有 和 - 操作这样订阅者只能有订阅或取消订阅操作没有权限执行其它操作。如果是委托那么订阅者就可以使用 来对委托对象重新赋值其它订阅者全部被取消订阅甚至将其设置为null甚至订阅者还可以直接调用委托。
事件保证了程序的安全性和健壮性。
7、事件的标准模式
.NET 框架为事件编程定义了一个标准模式。设定这个标准是为了让.NET框架和用户代码保持一致。System.EventArgs是标准模式的核心它是一个没有任何成员用于传递事件参数的基类。按照标准模式事件定义委托必须满足以下条件
1必须是 void 返回类型
2必须有两个参数且第一个是object类型第二个是EventArgs类型的子类
3它的名称必须以EventHandler结尾。
例如
using System;
namespace ConsoleApplication1
{class Program{static void Main(string[] args){Counter c new Counter(new Random().Next(10));c.ThresholdReached c_ThresholdReached;Console.WriteLine(press a key to increase total);Console.WriteLine(adding one);c.Add(1);while (Console.ReadKey(true).KeyChar a){Console.WriteLine(adding one);c.Add(1);}}static void c_ThresholdReached(object sender, ThresholdReachedEventArgs e){Console.WriteLine(The threshold of {0} was reached at {1}., e.Threshold, e.TimeReached);Environment.Exit(0);}}class Counter{private int threshold;private int total;public Counter(int passedThreshold){threshold passedThreshold;}public void Add(int x){total x;if (total threshold){ThresholdReachedEventArgs args new ThresholdReachedEventArgs();args.Threshold threshold;args.TimeReached DateTime.Now;OnThresholdReached(args);}}protected virtual void OnThresholdReached(ThresholdReachedEventArgs e){EventHandlerThresholdReachedEventArgs handler ThresholdReached;if (handler ! null){handler(this, e);}}public event EventHandlerThresholdReachedEventArgs ThresholdReached;}public class ThresholdReachedEventArgs : EventArgs{public int Threshold { get; set; }public DateTime TimeReached { get; set; }}
}