Explaining Delegates in C# - Part 1 (Callback and Multicast delegates)
I hear a lot of confusion around Delegates in C#, and today I am going to give it shot of explaining the stuff with easy to understand examples. First things first... I will consciously try NOT to use any technical jargon to explain this concept.
So here we go, without giving any technical explanation, let's start with a console application...
// Declaration
public delegate void VerySimpleDelegate(); class TestDelegate
{
public static void Foo()
{
Console.WriteLine("Foo was called by a delegate!");
} public static void Bar()
{
Console.WriteLine("Bar was called by a delegate!");
} public static void Main()
{
// Instantiation
VerySimpleDelegate vsd = new VerySimpleDelegate(Foo); //#1 // Invocation
vsd(); //Another Instantiation
vsd = Bar;
vsd();
}
}
What do you notice when you run the application? Yes, you are right... you are not calling the functions Foo and Bar directly! Instead, you are creating a delegate (#1). Also notice, you just assigned vsd = Bar, which was another function name. Calling vsd again in the next line called the function called Bar as you can see in the output below!!!
Thus, to use delegate you need to use the following approach... (check the comments in code snipped above to find the following)
Declaration
Instantiation
Invocation
May be you are thinking, why all this headache? What is the need to do all this?
Reason 1> You have to call different functions based on some dynamic requirement but you don't want your function calls to change. In our previous code snipped vsd() doesn't change, although the actual function that it is referring to has changed altogether.
Let's take a look at another sample... Example2
public class Example2
{
// Declaration - Take 1 parameter, return nothing
public delegate void LogHandler(string message); // Instantiation - Create a function which takes delegate as one parameter
// Verify if it is null before you use it
public void Process(LogHandler logHandler)
{
if (logHandler != null)
{
logHandler("Process() begin");
} if (logHandler != null)
{
logHandler("Process() end");
}
}
} public class Example2DelegateConsumer
{
// Create a method with the same signature as the delegate
static void Logger(string s)
{
Console.WriteLine(s);
} public static void Main(string[] args)
{
Example2 ex2 = new Example2(); // Invocation in the client
Example2.LogHandler myLogger = new Example2.LogHandler(Logger);
ex2.Process(myLogger);
}
}
Reason 2> As you can see above, you can use delegates to call static functions. In our case, the function Logger with a parameter was being called by Process function in the Example2 class. This approach is called Callback.
public class Example3
{
// Declaration - Take 1 parameter, return nothing
public delegate void LogHandler(string message); // Instantiation - Create a function which takes delegate as one parameter
// Verify if it is null before you use it
public void Process(LogHandler logHandler)
{
if (logHandler != null)
{
logHandler("Process() begin");
} if (logHandler != null)
{
logHandler("Process() end");
}
}
} public class FileLogger
{
FileStream fs;
StreamWriter sw; // Constructor
public FileLogger(string filename)
{
fs = new FileStream(filename, FileMode.Create);
sw = new StreamWriter(fs);
} // Create a method with the same signature as the delegate
public void Logger(string s)
{
sw.WriteLine(s);
} public void Close()
{
sw.Close();
fs.Close();
}
} public class Example3DelegateConsumer
{
static void Main(string[] args)
{
FileLogger fl = new FileLogger("C:\\Labfiles\\process.log");
Example3 ex3 = new Example3(); // Invocation in the client
// Notice that now instead of Logger function, we are passing fl.Logger function.
Example3.LogHandler myLogger = new Example3.LogHandler(fl.Logger);
ex3.Process(myLogger);
fl.Close();
}
}
Reason 3> Without changing the Example3 delegate, we were able to change the location where a log needs to be written. In the previous example, you would have noticed that we had a Logger function in the same class. Now, we know we can point to any function with the same signature as a delegate from a different class as well. In our example we called the function from the class FileLogger. The key here is that the Logger function is not in the Example3DelegateConsumer class!!!
What if you want to display the results, and write them at the same time??
namespace Delegates4
{
public class Example4
{
// Declaration - Take 1 parameter, return nothing
public delegate void LogHandler(string message); // Instantiation - Create a function which takes delegate as one parameter
// Verify if it is null before you use it
public void Process(LogHandler logHandler)
{
if (logHandler != null)
{
logHandler("Process() begin");
} if (logHandler != null)
{
logHandler("Process() end");
}
}
} public class FileLogger
{
FileStream fs;
StreamWriter sw; // Constructor
public FileLogger(string filename)
{
fs = new FileStream(filename, FileMode.Create);
sw = new StreamWriter(fs);
} // Create a method with the same signature as the delegate
public void Logger(string s)
{
sw.WriteLine(s);
} public void Close()
{
sw.Close();
fs.Close();
}
} public class Example4DelegateConsumer
{
// Create a method with the same signature as the delegate
static void Logger(string s)
{
Console.WriteLine(s);
} static void Main(string[] args)
{
FileLogger fl = new FileLogger("C:\\Labfiles\\process.log");
Example4 ex4 = new Example4(); // Invocation in the client
// Notice that now instead of Logger function, we are passing fl.Logger function
// along with another Logger which is defined in the same class
Example4.LogHandler myLogger = null;
myLogger += new Example4.LogHandler(Logger);
myLogger += new Example4.LogHandler(fl.Logger);
ex4.Process(myLogger);
fl.Close();
}
}
}
Reason 4> As you can see above, we have registered two methods for the same delegate. This is what is typically mentioned as Multicast delegate. By default in C#, delegates are multicast.
I hope this clarifies the basic concepts of delegates, and why you would use them in the first place. In the next post, I will tell you about how to use delegates for events.
转: http://www.dotnetscraps.com/dotnetscraps/post/explaining-delegates-in-c.aspx
Explaining Delegates in C# - Part 1 (Callback and Multicast delegates)的更多相关文章
- Explaining Delegates in C# - Part 7 (Asynchronous Callback - Way 4)
This is the final part of the series that started with... Callback and Multicast delegatesOne more E ...
- Explaining Delegates in C# - Part 6 (Asynchronous Callback - Way 3)
By now, I have shown the following usages of delegates... Callback and Multicast delegatesEventsOne ...
- C# delegate multicast single delegate
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serializatio ...
- Explaining Delegates in C# - Part 4 (Asynchronous Callback - Way 1)
So far, I have discussed about Callback, Multicast delegates, Events using delegates, and yet anothe ...
- Part 36 to 39 Talking about Delegates in c#
Part 36 Delegates in c# Part 37 Delegates usage in c# class Progim { public static void Main() { Lis ...
- c# 关键字delegate、event(委托与事件)[MSDN原文摘录][1]
A delegate is a type that safely encapsulates a method, similar to a function pointer in C and C++. ...
- c++中实现委托
成员函数指针与高性能的C++委托(上篇) 撰文:Don Clugston 引子 标准C++中没有真正的面向对象的函数指针.这一点对C++来说是不幸的,因为面向对象的指针(也叫做"闭包(clo ...
- 为 ngui TweenPosition 添加 pingpongone
//---------------------------------------------- // NGUI: Next-Gen UI kit // Copyright © 2011-2015 T ...
- koa2源码解读及实现一个简单的koa2框架
阅读目录 一:封装node http server. 创建koa类构造函数. 二:构造request.response.及 context 对象. 三:中间件机制的实现. 四:错误捕获和错误处理. k ...
随机推荐
- PHP 打乱数组
$arr = array( array( "id"=>1, "name"=>"张三", "sex"=> ...
- JAVA内部线程2
GC Daemon JVM GC Daemon线程是JVM为RMI提供远程分布式GC使用的,GC Daemon线程里面会主动调用System.gc()方法,对服务器进行Full GC. 其初衷是当RM ...
- FPGA内部动态可重置PLL讲解(二)
对于全局时钟的管理,涉及到关于亚稳态的知识,大家可以上网搜索相关资料,这里不再赘述.亚稳态最简单的理解形式是无法判断是处于高电平状态还是处于低电平状态,这样会导致整个系统不稳定,会出现逻辑上的错误. ...
- PoseNet: A Convolutional Network for Real-Time 6-DOF Camera Relocalization
用卷积神经网络对相机位置和角度进行回归.
- python3 异步模块asyncio
yield方法引入, 这里存在的问题是,如果你想创建从0到1,000,000这样一个很大的序列,你不得不创建能容纳1,000,000个整数的列表. 但是当加入了生成器之后,你可以不用创建完整的序列,你 ...
- Spring面试,IoC和AOP的理解
spring 的优点?1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦 2.可以使用容易提供的众多服务,如事务管理,消息服务等 3.容器提供单例模式支持 4.容器提供了AOP技术,利用它很容易实 ...
- VS自带的dbghelp.h文件 报错
场景: 编译报错: 解决方法: 在#include <dbghelp.h> 之前 #include <Windows.h>
- Swing 是一个为Java设计的GUI工具包
Swing 是一个为Java设计的GUI工具包. Swing是JAVA基础类的一部分. Swing包括了图形用户界面(GUI)器件如:文本框,按钮,分隔窗格和表. Swing提供许多比AWT更好的屏幕 ...
- unity执行顺序问题(如何再次执行start方法)
2016-09-08 20:13 2084人阅读 评论(1) 收藏 举报 分类: unity3D(66) 版权声明:本文为博主原创文章,未经博主允许不得转载. unity执行顺序的文章已经很多了, ...
- vimdiff的常用命令
★ 跳转到下一个diff点: 请使用 ]c 命令★ 跳转到前一个diff点: 请使用 [c命令如果在命令前加上数字的话,可以跳过一个或数个差异点,从而实现跳的更远.比如如果在位于第一个差异点的行输入& ...