C#语言的高级特性
一 C#的委托
委托的一般形式
例如public delegate double MyDelegate(int x)
委托的实例化 ,下面也就是说C#中的委托是如何去调用的
MyDelegate d1 = New MyDelegate(obj.MyMethod);
声明了一个委托d1。委托实际上是对函数原型的一个包装,obj.MyMethod就是这样的一个方法。
显然,obj.MyMethod是一个返回值为int类型的方法,而且这个方法已经被包装在了名为d1的这样的一
个委托中。
那么委托如何去调用呢
例如double r=d1(3);这样就非常的方便了,显然再调用obj.MyMethod的时候,就不用再次调用这样
的一个方法了。直接d1(3)就可以了。
有一个还没搞懂的代码例子
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Drawing; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { delegate double Fun(double x);//定义一个委托 double Square(double x) { return Math.Sqrt(Math.Sqrt(x)); } static double XPlus(double x) { return Math.Sin(x) + Math.Cos(x + 5) / 5; } private void Form1_paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; Pen pen = Pens.Blue; Fun[] funs = { new Fun(this.Square), new Fun(Form1.XPlus), new Fun(Math.Cos), new Fun(Math.Sqrt) }; foreach (Fun fun in funs) { PlotFun(fun, g, pen); } } void PlotFun(Fun fun,Graphics g,Pen pen) { for(double x=0;x<15;x+=0.1) { double y = fun(x); Point point = new Point((int)(x * 20), (int)(200 - y * 30)); g.DrawLine(pen, point, new Point(point.X + 2, point.Y + 2)); Console.WriteLine(" " + x + " " + y); } } static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } }
二 C#的事件
this.button1.Click+=new System.EventHandler(this.button1.Click);
事件的声明:
public event 委托名 事件名
事件名+= 和-= 作为事件的注册与移除
C#事件定义及使用的6步曲
1.公用,声明事件参数类
声明委托
2.在事件发生的类中
定义事件
发生事件
3 在事件处理的类中
定义一个方法
注册事件 xxx.事件+= new 委托(方法名)
实例,网络爬虫
using System; using System.Threading; namespace ConsoleApp1 { //1.1 声明参数类型 public class DownloadEventArgs : EventArgs { public double Percent; } //1.2 声明委托类型 public delegate void DownloadEventHandler(object sender, DownloadEventArgs args); //在事件发生的类中 public class Downloader { public event DownloadEventHandler Downloading;//定义事件,事件名为Downloading public void DoDownload() { double total = 10000; double already = 0; Random rnd = new Random(); while(already<total) { Thread.Sleep(500); already += (rnd.NextDouble() / 4) * total; if (already > total) already = total; if(Downloading!=null) { DownloadEventArgs args = new DownloadEventArgs(); args.Percent = already / total; Downloading(this, args); } } } } public class UseDownloader {
//定义事件处理的方法 private static void ShowProgress(object sender,DownloadEventArgs args) { Console.WriteLine($"Downloading...{args.Percent:##.##%}"); } static void Main() { var downloader = new Downloader(); //注册事件 downloader.Downloading+= ShowProgress; downloader.DoDownload(); Console.Read(); } } }
看起来很复杂,其实还是套路。
事件的触发需要 事件名(参数列表)
就如上面的事件Downloading ,
Downloading(this, args);
可以看到Main中,还是先实例化了一个Downloader的类,然后类实例化对象调用这个叫DoDownload的方法
这个方法中触发了Downloading这个事件,似乎调用一次这个事件,就会执行一次
ShowProgress
这个处理事件的方法。
args是传递信息的参数,,感觉可以视作参数类,,
三 Lambda表达式
一种简写方法
四 C#的运算符重载