`

C#委托,事件与回调函数

    博客分类:
  • C#
 
阅读更多
.Net编程中最经常用的元素,事件必然是其中之一。无论在ASP.NET还是WINFrom开发中,窗体加载(Load),绘制(Paint),初始化(Init)等等。
“protected void Page_Load(object sender, EventArgs e)”这段代码相信没有人不熟悉的。细心一点一定会发现,非常多的事件方法都是带了“object sender, EventArgs e”这两个参数。这是不是和委托非常相似呢?

一、委托(有些书中也称为委派)

委托是什么呢?这个名字的意思已经赋予了我们想象的空间,你是编程的,你现在正在写一个ASP.NET网页,而JS是你不熟悉的,于是你委托你的一位同事来帮助你完成JS部分。这就是委托,把你所不能做的事情交给其他人去做。而怎么知道是哪个人去做呢?当然是要知道名字!而为了区别名字一样的不同人,因此,需要描述一个特征。

在C#中,委托的作用是这样描述的:委托就像一个函数的指针,在程序运行时可以使用它们来调用不同的函数。这个其实和你委托同事完成 JS代码一样。如果有两位同事可以做这件事情,他们只要做的结果能够满足你的需求(就像一个接口),尽管他们做的过程不一样,并且作出的效果也不一样,但是,能够达到你的要求就可以了。

1、简单的委托

那委托需要承载哪些信息呢?首先,它存储了方法名,还有参数列表(方法签名),以及返回的类型。比如:
delegate string/*返回类型*/ ProcessDelegate(int i);
这就是一个委托的定义。蓝色部分是声明委托的关键字,红色部分是返回的类型,而黑色部分是委托的类型名,和一个类名差不多,而()里的就是参数部分。它的意思是,你要使用这个委托来做事情的话,那么,做事情的方法必须满足以下条件:
1、返回类型和委托的返回类型一致,这里是string类型;
2、能且只能有一个参数,并且是int类型。
OK,满足以上两个条件,一切就可以工作了:)

 
例如:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Text;
 4 
 5 namespace TestApp
 6 {
 7     /// <summary>
 8     /// 委托
 9     /// </summary>
10     /// <param name="s1"></param>
11     /// <param name="s2"></param>
12     /// <returns></returns>
13     public delegate string ProcessDelegate(string s1, string s2);
14 
15     class Program
16     {
17         static void Main(string[] args)
18         {
19             /*  调用方法  */
20             ProcessDelegate pd = new ProcessDelegate(new Test().Process);
21             Console.WriteLine(pd("Text1""Text2"));
22         }
23     }
24 
25     public class Test
26     {
27         /// <summary>
28         /// 方法
29         /// </summary>
30         /// <param name="s1"></param>
31         /// <param name="s2"></param>
32         /// <returns></returns>
33         public string Process(string s1,string s2)
34         {
35             return s1 + s2;
36         }
37     }
38 }

 

输出的结果是:
Text1Tex2


2、泛型委托

泛型的委托,就是然参数的类型不确定,例如代码改写为:

 

using System;
using System.Collections.Generic;
using System.Text;

namespace TestApp
{
    
/// <summary>
    
/// 委托
    
/// </summary>
    
/// <param name="s1"></param>
    
/// <param name="s2"></param>
    
/// <returns></returns>
    public delegate string ProcessDelegate<T,S>(T s1, S s2);

    
class Program
    {
        
static void Main(string[] args)
        {
            
/*  调用方法  */
            ProcessDelegate
<string,int> pd = new ProcessDelegate<string,int>(new Test().Process);
            Console.WriteLine(pd(
"Text1"100));
        }
    }

    
public class Test
    {
        
/// <summary>
        
/// 方法
        
/// </summary>
        
/// <param name="s1"></param>
        
/// <param name="s2"></param>
        
/// <returns></returns>
        public string Process(string s1,int s2)
        {
            
return s1 + s2;
        }
    }
}

 

输出的结果就是:
Text1100

泛型的详细内容不属于本文的介绍范围,这里不加多说了。

二、事件

在某件事情发生时,一个对象可以通过事件通知另一个对象。比如,前台完成了前台界面,他通知你,可以把前台和你开发的程序整合了。这就是一个事件。可以看出事件是在一个时间节点去触发另外一件事情,而另外一件事情怎么去做,他不会关心。就事件来说,关键点就是什么时候,让谁去做。

在C#中,时间定义关键字是event。例如:
event ProcessDelegate ProcessEvent;

整个事件定义方法以及执行过程:

 

using System;
using System.Collections.Generic;
using System.Text;

namespace TestApp
{
    
/// <summary>
    
/// 委托
    
/// </summary>
    
/// <param name="s1"></param>
    
/// <param name="s2"></param>
    
/// <returns></returns>
    public delegate void ProcessDelegate(object sender, EventArgs e);

    
class Program
    {
        

        
static void Main(string[] args)
        {
            
/*  第一步执行  */
            Test t 
= new Test();
            
/* 关联事件方法,相当于寻找到了委托人 */
            t.ProcessEvent 
+= new ProcessDelegate(t_ProcessEvent);
            
/* 进入Process方法 */
            Console.WriteLine(t.Process()); 

            Console.Read();
        }

        
static void t_ProcessEvent(object sender, EventArgs e)
        {
            Test t 
= (Test)sender;
            t.Text1 
= "Hello";
            t.Text2 
= "World";
        }
    }

    
public class Test
    {
        
private string s1;

        
public string Text1
        {
            
get { return s1; }
            
set { s1 = value; }
        }

        
private string s2;

        
public string Text2
        {
            
get { return s2; }
            
set { s2 = value; }
        }


        
public event ProcessDelegate ProcessEvent;

        
void ProcessAction(object sender, EventArgs e)
        {
            
if (ProcessEvent == null)
                ProcessEvent 
+= new ProcessDelegate(t_ProcessEvent);
            ProcessEvent(sender, e);
        }

        
//如果没有自己指定关联方法,将会调用该方法抛出错误
        void t_ProcessEvent(object sender, EventArgs e)
        {
            
throw new Exception("The method or operation is not implemented.");
        }

        
void OnProcess()
        {
            ProcessAction(
this, EventArgs.Empty);
        }

        
public string Process()
        {
            OnProcess();
            
return s1 + s2;
        }
    }
}
 

 

感觉到了什么?是不是和代码注入了差不多,相当于是可以用任意符合委托接口(委托确实很像接口)的代码,注入到Process过程。在他返回之前给他赋值。

三、回调函数

打了这么多字,好累啊!

回调函数就是把一个方法的传给另外一个方法去执行。在C#有很多回调函数,比如异步操作的时候。这里先举个例子:

 

using System;
using System.Collections.Generic;
using System.Text;

namespace TestApp
{
    
/// <summary>
    
/// 委托
    
/// </summary>
    
/// <param name="s1"></param>
    
/// <param name="s2"></param>
    
/// <returns></returns>
    public delegate string ProcessDelegate(string s1, string s2);

    
class Program
    {
        
static void Main(string[] args)
        {
            
/*  调用方法  */
            Test t 
= new Test();
            
string r1 = t.Process("Text1""Text2"new ProcessDelegate(t.Process1));
            
string r2 = t.Process("Text1""Text2"new ProcessDelegate(t.Process2));
            
string r3 = t.Process("Text1""Text2"new ProcessDelegate(t.Process3));

            Console.WriteLine(r1);
            Console.WriteLine(r2);
            Console.WriteLine(r3);
        }
    }

    
public class Test
    {
        
public string Process(string s1,string s2,ProcessDelegate process)
        {
            
return process(s1, s2);
        }

        
public string Process1(string s1, string s2)
        {
            
return s1 + s2;
        }

        
public string Process2(string s1, string s2)
        {
            
return s1 + Environment.NewLine + s2;
        }

        
public string Process3(string s1, string s2)
        {
            
return s2 + s1;
        }
    }
}

 

输出结果:
Text1Text2
Text1
Text2
Text2Text1

Process方法调用了一个回调函数,当然这里只执行了回调函数。可以看出,可以把任意一个符合这个委托的方法传递进去,意思就是说这部分代码是可变的。而设计上有一个抽离出可变部分代码的原则,这种用法无疑可以用到那种场合了。

 

分享到:
评论

相关推荐

    详解C#委托,事件与回调函数

    详解 C# 委托、事件与回调函数 委托是 C# 中一种非常重要的概念,它可以将方法作为参数传递给其他方法,也可以将方法作为返回值返回给其他方法。委托的定义是:delegate 返回类型 委托名(参数列表);例如:...

    C#委托与C++回调函数处理

    本文将深入探讨C#中的委托以及C++中的回调函数,并阐述如何在C#中处理C++定义的回调函数。 首先,让我们理解C#中的委托。委托在C#中是一种类型安全的事件处理机制,它类似于函数指针,但又有所不同。委托可以引用一...

    19.C#中委托、事件和回调函数的理解.pdf

    总结来说,委托、事件和回调函数是C#中用于实现解耦和事件驱动编程的重要机制。委托可以引用方法,事件是特殊的委托,通过事件发布者和订阅者模型允许对象之间进行通信。回调函数则是委托的一种应用,它允许在特定...

    C# 实现回调函数

    回调函数在编程中是一种强大的...总结来说,C#中的回调函数通过委托、事件和lambda表达式等方式实现,它们在异步编程、事件处理和算法定制等方面发挥着重要作用。理解和熟练运用回调函数,能让你的C#代码更加灵活高效。

    C#回调函数

    在C#编程中,回调函数是一种非常重要的设计模式,它允许我们传递一个方法作为参数到另一个方法中,以便在特定事件发生或者特定条件满足时执行。这种机制使得代码具有高度的灵活性和可扩展性,特别是在处理异步操作、...

    C#回调函数示例

    在C#中,回调函数同样被广泛使用,尤其是在异步编程、事件处理和自定义算法中。本示例将通过VS2013环境,探讨如何在C#中实现和应用回调函数。 首先,我们需要理解回调函数的基本概念。回调函数本质上是一个在其他...

    c#委托回调函数

    在.NET框架中,C#语言提供了强大的特性来处理异步编程,其中委托和回调函数是核心部分。本文将深入探讨C#中的委托和回调函数,以及如何在多线程环境中应用它们。 首先,理解委托的概念至关重要。委托在C#中相当于...

    C#调用C++动态库中自身定义的回调函数

    总结来说,C#调用C++动态库并处理回调函数的关键在于正确地定义C++的函数接口,创建匹配的C#委托类型,使用P/Invoke进行调用,并注册合适的回调方法。这种技术在需要高性能计算、利用现有C++库或者与其他系统交互时...

    C#实现C++dll回调函数.rar

    总结,这个示例涉及了C#与C++之间的互操作,尤其是回调函数的使用。这种技术在游戏开发、图形库、硬件驱动等领域非常常见,它允许我们利用C++的性能优势和C#的高级特性,构建出高效且灵活的软件系统。理解和掌握这些...

    C#在C++中注册回调函数

    C#定义回调函数和委托,通过P/Invoke暴露给C++;C++/CLI作为桥梁,将C++的函数指针转换为C#的委托;最后,C++调用C++/CLI方法,完成回调函数的注册。这个过程需要对两种语言的互操作性有深入理解,包括内存管理、...

    c#线程结束后,实现的委托回调函数源码

    本篇将深入探讨如何在C#中实现线程结束后的委托回调功能,并安全地访问主线程中的控件。 首先,理解线程和委托的概念至关重要。线程是程序执行的流程,每个进程至少有一个线程。委托是C#中的一种类型,它类似于函数...

    C#传递回调函数

    ATL调用这个回调函数来通知C#代码某些事件或执行特定的操作。 首先,让我们理解回调函数的基本概念。回调函数本质上是一个在其他函数内部被调用的函数,它的功能是在适当的时候执行预先定义好的行为。在C#中,我们...

    C# Csharp 调用 C++的DLL中的回调函数

    4. 委托与C++回调的映射:C#委托类型与C++回调函数的原型匹配。 5. 多线程安全:在多线程环境中使用回调时,需要注意线程同步和数据一致性。 这个示例对理解和实践C#与C++的交互非常有帮助,特别是对于那些需要在...

    C#委托,事件与回调.docx

    例如,在使用 WebClient 下载文件时,可以使用回调函数来处理下载完成后的事件。 委托、事件和回调是 C# 编程中三个紧密相关的概念,它们都是.Net 编程中最常用的元素。理解它们之间的关系和实现方式对于提高编程...

    C#委托事件与回调测试

    **回调函数**是指在某个操作完成时,用来通知调用者的方法。在C#中,通常通过委托来实现回调。当线程A完成任务后,可以调用一个回调方法,让线程B知道任务的状态。 例如,假设我们有一个名为`BackgroundWorker`的类...

    详解C#委托,事件与回调函数

    .Net编程中最经常用的元素,事件必然是其中之一。无论在ASP.NET还是WINFrom开发中,窗体加载(Load),绘制(Paint),初始化(Init)等等。“protected void Page_Load(object sender, EventArgs...这是不是和委托非常相似呢?

    C#调用C++动态库,执行回调函数并传递结构体参数

    在C#中定义回调函数的委托类型: ```csharp [UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate void CallbackDelegate(ref SomeStruct structure); ``` 其中`SomeStruct`是C#中定义的结构体,需要...

    c#的回调函数(delegate关键字)

    C#中的委托(Delegate) 在C#中,委托(Delegate)是一种特殊的类型,用于封装方法的引用。它可以将方法作为参数传递,类似于C++中的函数指针,但是委托是类型安全和可靠的。 在上面的代码中,我们定义了一个委托...

    C# 回调CV++ DLL 三种方法 和 多类之间共享一个回调函数

    在C++ DLL中,你需要定义一个与`CallbackDelegate`签名相匹配的函数指针类型,并创建一个全局变量或静态成员来存储回调函数。 回调函数是跨语言和跨进程通信中的关键组件,正确理解和使用回调能够帮助我们构建灵活...

Global site tag (gtag.js) - Google Analytics