委托是一种函数引用的Object,实际上是用类完成了函数指针的功能
C#中的委托(Delegate)类似于C或C++中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。
委托(Delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生 自System.Delegate 类。
1,声明委托:
Delegate void Print(int x)
2,初始化,给委托赋值
3,调用委托变量
SomeFunc(x);
委托是将函数指针和实例对象打包在一起的类,它有两个重要的成员,一个用来保存实例对象,一个用来保存函数的指针。从源码中可以查看System.Delegate

我们查看System.Delegate的属性,可以看到一个属性Target
public Object Target
{
get
{
return GetTarget();
}
}
看一下GetTarget的功能
internal virtual Object GetTarget()
{
return (_methodPtrAux.IsNull())?_target:null;
}
意思就是当把一个静态方法给委托的时候将会返回一个null,如果是一个实例方法时, 将会返回当前方法所在的实例对象(this)
下面用一段代码演示一下:
using System;
//声明委托
public delegate void Print(int x);
namespace ConsoleApp1
{
public class Test
{
//实例方法
public void Test1(int x)
{
Console.WriteLine("实例方法,数字:{0}",x);
}
//静态方法
public static void Test2(int x)
{
Console.WriteLine("静态方法,数字:{0}",x);
}
}
class Program
{
static void Main(string[] args)
{
//委托的使用
Test t = new Test();//实例对象
Print p1 = new Print(t.Test1);//委托赋值
p1(25);//调用委托
Print p2 = Test.Test2;//委托赋值
p2(33);//调用委托
//委托原理
Console.WriteLine(p1.Target is Test);//实例方法-判断Target是不是指向方法所在的对象
Console.WriteLine(p2.Target is Test);//静态方法-判断Target是不是null
Console.ReadLine();
}
}
}
输出结果
实例方法,数字:25
静态方法,数字:33
True
False
也就是如果Target属性为null说明是静态方法的委托,如果不为null说明是实例方法的 委托
需要注意的是声明的委托类型和被委托的函数类型以及参数要一致,如果委托没有返回 值,那么被委托的函数也要没有返回值,如果委托有参数,那么被委托的函数和委托的 参数类型要一致。
通过这个代码就可以很直白的看出委托的作用,就是将方法封装在委托中,然后就可以将委托对象传递给可调用所引用方法的代码,不必在编译时知道将要调用那个方法。
前面是自己定义的委托,但是系统也提供了两种委托:Action和Func,Action用于不需 要返回值的委托,Func适合需要返回值的委托
1,Action委托 封装一个方法,该方法不具有参数并且不返回值
2,Action<T>委托 封装一个方法,该方法只有一个参数并且不返回值
3,Action<T1,T2>委托 封装一个方法,该方法具有两个参数并且不返回值
最多有16个参数
1,Func(TResult)委托封装封装一个不具有参数但却返回 TResult 参数指定的类型值的方 法
2,Func(T,TResult)委托 封装一个具有一个参数并返回 TResult 参数指定的类型值的方法
3,Func(T1,T2,TResult)委托 封装一个具有两个参数并返回 TResult 参数指定的类型值的方 法
其中的T是参数类型,TResult是返回值类型
下面用一个例子演示:
using System;
namespace ConsoleApp1
{
public class Test
{
//Action示例
public void Test1(int x)
{
Console.WriteLine("打印数字:"+x);
}
//Func示例
public int Test2(int n)
{
return n;
}
}
class Program
{
static void Main(string[] args)
{
//系统内置委托的使用
Test t = new Test();//实例对象
Action<int> ac1 = new Action<int>(t.Test1);//委托赋值
ac1(22);//调用委托
Func<int, int> ac2 = new Func<int, int>(t.Test2);//委托赋值
Console.WriteLine(ac2(233));//调用委托
Console.ReadLine();
}
}
}
输出结果:
打印数字:22
233
多播委托是指在一个委托中注册多个方法,在注册方法时可以在委托中使用加号运算符
或者减号运算符来实现添加或撤销方法。
比如现实的点餐系统,可以点甜食,面食,水果等,在这里委托相当于点餐平台,每一 个类型的商品可以理解为在委托商注册的一个方法。
使用委托的这个有用的特点,可以创建一个委托被调用时要调用的方法的调用列表。 这被称为委托的 多播(multicasting),也叫组播。
下面的程序演示了委托的多播:
using System;
//声明委托
public delegate void Order();
namespace ConsoleApp1
{
public class Test
{
//买水果
public void Test1()
{
Console.WriteLine("购买水果!");
}
//买甜食
public static void Test2()
{
Console.WriteLine("购买甜食!");
}
}
class Program
{
static void Main(string[] args)
{
//多播委托
Test t = new Test();//实例对象
Order order =new Order(t.Test1);//委托赋值-实例方法
order += new Order(Test.Test2);//委托赋值-静态方法
order();//调用委托
Console.ReadLine();
}
}
}
输出结果:
购买水果!
购买甜食!
通过这个例子可以看出来,我们把两个方法都注册到了一个委托上面,并且调用委托一 下调用了两个方法,先调用了购买水果的方法,然后调用了购买甜食的方法。
在使用多播委托时需要注意,在委托中注册的方法参数列表必须与委托定义的参数列表 相同,否则不能将方法添加到委托上。
如有错漏之处,敬请指正!
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主
我正在学习Ruby,遇到了inject。我正处于理解它的风口浪尖,但当我是那种需要真实世界的例子来学习一些东西的人时。我遇到的最常见的例子是人们使用inject来添加一个(1..10)范围的总和,我不太关心这个。这是一个任意的例子。在实际程序中我会用它做什么?我正在学习,所以我可以继续使用Rails,但我不必有一个以Web为中心的示例。我只需要一些我可以全神贯注的目标。谢谢大家。 最佳答案 inject有时可以通过它的“其他”名称reduce更好地理解。它是一个对Enumerable进行操作(迭代一次)并返回单个值的函数。它有许多有
我有以下类(class):classAlphabetattr_reader:letter_freqs,:statistic_letterdefinitialize(lang)@lang=langcaselangwhen:en@alphabet=('A'..'Z').to_a@letter_freqs={...}when:ru@alphabet=('А'..'Я').to_a.insert(6,'Ё')@letter_freqs={...}...end@statistic_letter=@letter_freqs.max_by{|k,v|v}[0]endendfoo=Alphabet.n
我如何做Ruby方法"Flatten"RubyMethod在C#中。此方法将锯齿状数组展平为一维数组。例如:s=[1,2,3]#=>[1,2,3]t=[4,5,6,[7,8]]#=>[4,5,6,[7,8]]a=[s,t,9,10]#=>[[1,2,3],[4,5,6,[7,8]],9,10]a.flatten#=>[1,2,3,4,5,6,7,8,9,10 最佳答案 递归解决方案:IEnumerableFlatten(IEnumerablearray){foreach(variteminarray){if(itemisIEnume
我最近从C#转向了Ruby,我发现自己无法制作可折叠的标记代码区域。我只是想到做这种事情应该没问题:classExamplebegin#agroupofmethodsdefmethod1..enddefmethod2..endenddefmethod3..endend...但是这样做真的可以吗?method1和method2最终与method3是同一种东西吗?还是有一些我还没有见过的用于执行此操作的Ruby惯用语? 最佳答案 正如其他人所说,这不会改变方法定义。但是,如果要标记方法组,为什么不使用Ruby语义来标记它们呢?您可以使用
什么是Linq聚合方法的ruby等价物。它的工作原理是这样的varfactorial=new[]{1,2,3,4,5}.Aggregate((acc,i)=>acc*i);每次将数组序列中的值传递给lambda时,变量acc都会累积。 最佳答案 这在数学以及几乎所有编程语言中通常称为折叠。它是更普遍的变形概念的一个实例。Ruby从Smalltalk中继承了这个特性的名称,它被称为inject:into:(像aCollectioninject:aStartValueinto:aBlock一样使用。)所以,在Ruby中,它称为inj
我在尝试使用Faraday将文件上传到网络服务时遇到问题。我的代码:conn=Faraday.new('http://myapi')do|f|f.request:multipartendpayload={:file=>Faraday::UploadIO.new('...','image/jpeg')}conn.post('/',payload)尝试发布后似乎没有任何反应。当我检查响应时this是我所看到的:#:post,:body=>#,#,@opts={}>,#],@index=0>>,#>],@ios=[#,#,@opts={}>,#],@index=0>,#],@index=0>