C#委托与事件总结

目录

C#委托与事件的总结

1.概述

委托与事件是C# 1.0版本的新特性,与C# 1.0版本对应的是.NET Framework 1.0,发布于2002年1月,在这个版本中C#还提供了编程语言基础特性:

  • Classes:面向对象特性,支持类类型
  • Structs:结构
  • Interfaces:接口
  • Events:事件
  • Properties:属性,类的成员,提供访问字段的灵活方法
  • Delegates:委托,一种引用类型,表示对具有特定参数列表和返回类型的方法的引用
  • Expressions,Statements,Operators:表达式、语句、操作符
  • Attributes:特性,为程序代码添加元数据或声明性信息,运行时,通过反射可以访问特性信息
  • Literals:字面值(或理解为常量值),区别常量,常量是和变量相对的

本篇博文将通过一个事例来说明委托与事件,其中包括了委托的定义,委托的使用,事件是如何产生(在这之中将说明事件与委托的关系),以及委托与事件特性有什么优势,为什么要去定义这一特性,我们为什么要去使用这一特性。

本篇博文是对大牛们的博客与书籍的学习总结,可能会有雷同之处,如若侵权,烦请告知,立即删除。

本篇博文只是一名初学者的皮毛见解,仅供以学习交流,如有错误之处,烦请指出校正,如若希望更深入的学习或者得到更清晰的描述,请前往各位大牛的博客,链接地址将在参考目录中给出。

2.委托

2.1 什么是委托

在生活中我们遇到过许多委托,子学校里不想去上课,我们也许会委托室友答到,在法庭上,辩护人会委托律师为其进行辩护。生活中有许多这样的例子,单子啊C#中,委托是什么样子呢?

委托在C/C++中可以理解为函数指针,党调用这个指针时,便执行了这个指针所指向的函数,在C#中可以理解为函数的一个包装,调用委托时便执行了该函数。

C/C++通过函数指针获得了函数的入口地址,通过调用函数指针来实现对函数的操作

要怎樣去理解呢?我們以A同學委託B同學答到這一事例來模擬一下,A同學是一個類class A,有一個答到方法public void Dadao(string name),答到方法有一個參數name提供了A同學的名字,現在A同學想睡懶覺不想去上課了,他委託了室友B去答到,黨老師叫到A的時候,B便會說:“A,到!”(我們只用調用B便會得到調用A類中Dadao方法的結果),具體代碼參見代碼清單 2-1

public class A
{
    public void Dadao(string name)
    {
        Console.WriteLine("A,到!");
    }
}

public delegate void DadaoHandler();

class MainEntry
{
    static void Main()
    {
        DadaoHandler B = 
            new DadaoHandler(new A().Dadao);
        
        B("A");
    }
}
代码清单 2-1

或許這個事例說明的有點彆扭,不妨換個事例,還是同學A與同學B之間的故事,B是我們高中班上的美女小組長,A是我們的猥瑣後桌。

我們每天上學要做的第一件事是什麼?對了,交作業!美麗的清晨,東方才微微泛出陽光,空氣中充滿了泥土的清香,美女小組長B跟猥瑣后桌B說:“那誰,emmm,帥哥,等下幫我收下作業唄,我去看體育生學長晨練了~”,那誰非常高興的答應了,老師來了說把作業收起來,我們的A哥便馬上屁顛屁顛的去收作業了,收的時候還不忘向你嘚瑟下。

這個事例中,美女小組長B委託了猥瑣后桌A收作業。B中有收作業的方法,當老師調用A時,便調用了B中的收作業方法。

2.2 委託的使用

下面將會通過模擬接待外賓時,廚師、服裝師所做的準備。我們有一個廚師類,一個服裝師類,廚師類有個烘焙蛋糕的方法,服裝師類有個穿正裝的方法,我們聲明了一個外賓接待委託。我們將以這個事例來說明委託的聲明、實例化以及綁定,详细代码请参考代码清单2-2

2.2.1 委託的申明

前面我們說過,委託是方法的一個包裝。它與方法有著相同的方法簽名和返回類型。

[訪問修飾符] delegate return_type handler_name(args_type args);

現在我們的廚師class Cook有一個烘焙蛋糕的方法void BakeCoke(string name);,我們的服裝師class Dress有一個穿正裝的方法void FormalWear(string name);其中name是外賓的名字。現在我們為這兩個方法創建一個委託,我們可以使用一下申明:

public delegate void ForeignHandler(string name);

方法簽名相同:方法的參數個數、順序、類型相同

2.2.2 委託的實例化

現在我們將ForeignHandler實例化,將需要委託的方法作為構造函數參數來實例化委託。

ForeignHandler fg_handler = new ForeignHandler(new Cook().BackCoke);

當然,靜態方法也可以進行委託,現在我們將烘焙蛋糕的方法設置為靜態方法static void BakeCoke(string name);

ForeignHandler fg_handler = Cook.BakeCoke;

2.2.3 方法绑定委托

绑定是委托的一个特性,它能让我们在一个委托事例中绑定多个方法,不需要去为每个方法去实例化一个委托。绑定符号为+=,当然我们可以使用-=来解除绑定。当将方法绑定到委托上后,调用委托时,绑定在这个委托上的所有方法都会被执行。

fg_handler += new Dress().FormalWear;

2.3 深入理解委托

现在我们知道了怎样去使用委托,但我们要怎样去理解委托?其实,大家应该有了一个认识,委托其实就是一个类,我们对委托的一些操作其实就是对类的操作,只是有一些特殊之处。

现在我们不使用委托来实现包装Cook.BakeCoke方法,我们需要怎样做?我们需要定义一个方法void function();,然后需要一个参数来接收BakeCoke方法,所以我们的方法变为了void function(*** MakeBakeCoke);,因为BakeCoke方法中有一个name参数,所以我们需要为function添加一个string类型的参数,最终,这个方法便如下所示:

public void function(string name, *** MakeBakeCoke)
{
    MakeBakeCoke(name);
}

但是是,我们不知道MakeBakeCoke的类型,也就是说***具体应该怎样写?现在我们有了委托,一切问题都解决了,我们声明一个委托类型,然后将委托类型写在这就可以了。

2.4 为什么要使用委托

委托能够有效的为代码解耦,提高代码的可扩展性,具体如何尚在学习之中,在参考目录中有对于代码耦合度的相关链接,大家可以前往进行学习。

2.5 代码清单

namespace Event
{
    public delegate void ForeignHandler(string name);

    public class Cook
    {
        public void BakeCoke(string name)
        {
            Console.WriteLine("Your Majesty,We'll baking coke for " + name);
        }
    }

    public class Dress
    {
        public void FormalWear(string name)
        {
            Console.WriteLine("Yor Majesty, You'll wear formal to meeting " + name);
        }
    }
    
    public class MeetingForeignManage
    {
        public void MeetingForeign(string name, ForeignHandler make_meeting)
        {          
            make_meeting(name);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //  實例化委託
            //  ForeignHandler fg_handler;
            //  fg_handler = new CookServant().BakeCoke;
            ForeignHandler fg_handler =
                new ForeignHandler(new Cook().BakeCoke);

            //  綁定委託
            fg_handler += new Dress().FormalWear;
            //  調用委託
            MeetingForeignManage mt_fg = new MeetingForeignManage();
            mt_fg.MeetingForeign("Jorge King", fg_handler);


            Console.Read();
        }
    }
}
代碼清單2-2

3.事件与委托的关系

    public class MeetingForeignManage
    {
        public ForeignHandler fg_handler;

        public void MeetingForeign(string name, ForeignHandler make_meeting)
        {          
            make_meeting(name);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MeetingForeignManage mt_fg = new MeetingForeignManage();
            mt_fg.fg_handler = new Cook().BakeCoke;
            mt_fg.fg_handler += new Dress().FormalWear;
            mt_fg.MeetingForeign("Jorge King", mt_fg.fg_handler);

            Console.Read();
        }
    }
代碼清單1-2
    public class MeetingForeignManage
    {
        public ForeignHandler fg_handler;

        public void MeetingForeign(string name)
        {
            if (fg_handler != null)
            {
                fg_handler(name);
            }            
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MeetingForeignManage mt_fg = new MeetingForeignManage();
            mt_fg.fg_handler = new Cook().BakeCoke;
            mt_fg.fg_handler += new Dress().FormalWear;
            mt_fg.MeetingForeign("Jorge King");

            Console.Read();
        }
    }
代碼清單1-3
    public class MeetingForeignManage
    {
        public event ForeignHandler fg_event;

        public void MeetingForeign(string name)
        {
             fg_event(name);            
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MeetingForeignManage mt_fg = new MeetingForeignManage();
            mt_fg.fg_event += new Cook().BakeCoke;
            mt_fg.fg_event += new Dress().FormalWear;
            mt_fg.MeetingForeign("Jorge King");

            Console.Read();
        }
    }
代碼清單1-4
namespace Event
{
    public delegate void ForeignHandler(string name);

    //  訂閱者(監視者)
    public class Cook
    {
        public void BakeCoke(string name)
        {
            Console.WriteLine("Your Majesty,We'll baking coke for " + name);
        }
    }

    //  訂閱者(監視者)
    public class Dress
    {
        public void FormalWear(string name)
        {
            Console.WriteLine("Yor Majesty, You'll wear formal to meeting " + name);
        }
    }

    //  發佈者(監視對象)
    public class Emperor
    {
        public event ForeignHandler fg_event;

        public void MeetingWithForeignGuests(string fg_name)
        {
            Console.WriteLine("We need meeting with foreign guests.");

            if (fg_event != null)
            {
                fg_event(fg_name);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string fg_name = "Jorge King";

            Emperor fg_coming = new Emperor();

            //  使Cook和Dress訂閱事件
            fg_coming.fg_event += new Cook().BakeCoke;
            fg_coming.fg_event += new Dress().FormalWear;

            fg_coming.MeetingWithForeignGuests(fg_name);

            Console.Read();
        }
    }
}
代碼清單1-5

4.參考目錄

猜你喜欢

转载自www.cnblogs.com/Yuzex96ch/p/9841126.html