一起谈.NET技术,.NET Framework源码研究系列之---Delegate

简介:   前言  曾几何时能看到微软产品的源码简直是天方夜谭,不过现在这却成了现实,微软终于对外开放了它的产品的源代码.抛去开源运动与微软之间的世代情仇,抛去微软这一做法的初衷,这总归是件好事,能够让我们拨开云雾,一窥优秀产品的秘密.

  前言

  曾几何时能看到微软产品的源码简直是天方夜谭,不过现在这却成了现实,微软终于对外开放了它的产品的源代码.抛去开源运动与微软之间的世代情仇,抛去微软这一做法的初衷,这总归是件好事,能够让我们拨开云雾,一窥优秀产品的秘密.

  前两天看到有位仁兄在随笔中的留言,说他以为".NET中的设计模式"是在讲.NET Framework与设计模式的关系,其实不是,不过这也让我想起来自己确实研究过.NET Framework的源码,于是就找打算找时间把自己的心得体会拿出来和大家一起分享.

  今天就先从最容易让人困惑的委托(delegate)开始,让我们步入.NET Framework源码世界,共同学习优秀的程序设计.

  先看委托的定义:用于声明一个引用类 型,该引用类型可用于封装命名方法或匿名方法。委托类似于 C++ 中的函数指针;但是,委托是类型安全和可靠的。

  相信看到这段话之后,很多人,包括我自己就开始一起探索委托函数指针,于是各种网文就出现了.但委托到底是什么呢?我们先看一段很简单的代码:

 
 
public delegate void OnAction( int flag);

  这里我们定义了一个最简单的委托:OnAction.MSDN解释Delegate 类是委托类型的基类,但只有系统和编译器可以显式地从 Delegate 类或 MulticastDelegate 类派生.那么我们可以认为OnAction是从delegate继承过来的,只是不能显式的继承,由系统代做了.

  接下来让我们看一下微软是怎么定义委托的:

 
 
[Serializable()]
[ClassInterface(ClassInterfaceType.AutoDual)]
[System.Runtime.InteropServices.ComVisible(
true )]
public abstract class Delegate : ICloneable, ISerializable

由此可以看出delegate是个抽象类,并且实现了 ICloneable, ISerializable两个接口,并且有ClassInterface(ClassInterfaceType.AutoDual)这么一个属性.这有很多问题.

  首先,委托是个抽象类,所以要使用的必须继承,但是委托又跟整型一样,是一种类型,由此就可以理解问什么"Delegate 类是委托类型的基类,但只有系统和编译器可以显式地从 Delegate 类或 MulticastDelegate 类派生"这句话的意思了,因为不可能从整型继承过来一个子类,那么委托为什么是一个类而不像整型一样是一个结构呢?这个问题下面回答.

  其次,这也是我觉得不理解的地方,委托实现了ICloneable, ISerializable两个接口,也就是说委托可以被克隆和序列化.相信大家没人会写OnAction.Clone();这么一句话.浅表克隆一个委托实在有点费解.不过,如果可以从良好的编程习惯上解释为什么事先ICloneable接口的话,委托对ISerializable的实现就更让人困惑了,因为可能因此导致一些莫名其妙的编译时错误.我曾经遇到这样一个Bug,一个标记序列化的单件实体类包含一个事件(事件默认实现了ISerializable),该事件导致序列化的时候在凡是跟该事件的引用有关的地方全部报出莫名其妙的未标记序列化的错误,最终的解决办法是需要将该事件标记为[NonSerialized].

      下面看一下具体是怎么实现委托的:

 代码

  上面代码显示委托类包含4个internal类型的字段,从其注释我们大致可以看出_target是我们要调用的对象,_methodBase是给委托赋值时传递的方法,_methodPtr是指向该方法的指针,_methodPtrAux同静态类型委托的methodPtr指向的内容一样,只是少了对象的引用. 在看委托类的三个构造函数,一个是私有的,是用来防止实例化的,另外2个差不多,做的事情是把一个方法绑定到一个对象上.这里的方法应该是我们赋给委托的方法,对象则是编译器自己来维护的对象.这里调用了一个方法BindToMethodName,在源码中看不到实现,仅能看到如下内容:

 
 
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern bool BindToMethodName(Object target, RuntimeTypeHandle methodType, String method, DelegateBindingFlags flags);

  MethodImplAttribute标签表明了该方法为CLR内部方法,具体是什么,我们不得而知.此类的方法还有很多,就不一一例举.说到这个地方,我们可以发现上面说的"OnAction是从delegate继承过来的"和"Delegate 类是委托类型的基类"并不正确,正确的理解应该是delegate类在内部管理了一个用于绑定方法的对象,这点也可以从OnAction反汇编出来的构造函数看出:

代码
 
  
.method public hidebysig specialname rtspecialname
instance
void .ctor( object ' object ' ,
native
int ' method ' ) runtime managed
{
}
// end of method OnAction::.ctor

  另外delegate中还有一个静态方法:

public static Delegate CreateDelegate(Type type, Object firstArgument, MethodInfo method, bool throwOnBindFailure)

该方法前后有11个重载,其方法体里无一不包括:

代码
 
  
Delegate d = InternalAlloc(type.TypeHandle);
if ( ! d.BindToMethodInfo(firstArgument, method.MethodHandle, method.DeclaringType.TypeHandle,
DelegateBindingFlags.RelaxedSignature))
{
if (throwOnBindFailure)
throw new ArgumentException(Environment.GetResourceString( " Arg_DlgtTargMeth " ));
d
= null ;
}

  这样一段代码.其中InternalAlloc,BindToMethodInfo与BindToMethodName一样,都属于CLR内部方法.具体是什么一样看不出,只能大致猜测CLR内部生成了一个委托对象,然后将我们定义的委托签名,方法,方法引用等一些内容交给委托类来维护.

  通过以上分析,我们发现如它的定义,委托本质上是一个类,它的职责是代替我们管理维护方法调用.这一切无论从功能,还是外面,其实跟函数指针没有半点关系.至此,相信大家对delegate有了不一样的认识,同时也发现C#仅仅是CLR的一层外壳,并没有涉及到很核心的内容.

       以上仅仅是我个人的一点看法,由于本人水平有限,认识上难免有不正确的地方,如果你有更好的见解,敬请指正.

目录
相关文章
|
27天前
|
开发框架 安全 .NET
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱
在数字化时代,.NET 技术凭借跨平台兼容性、丰富的开发工具和框架、高效的性能及强大的安全稳定性,成为软件开发的重要支柱。它不仅加速了应用开发进程,提升了开发质量和可靠性,还促进了创新和业务发展,培养了专业人才和技术社区,为软件开发和数字化转型做出了重要贡献。
24 5
|
27天前
|
传感器 人工智能 供应链
.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。
本文深入探讨了.NET开发技术在数字化时代的创新作用,从高效的开发环境、强大的性能表现、丰富的库和框架资源等方面揭示了其关键优势。通过企业级应用、Web应用及移动应用的创新案例,展示了.NET在各领域的广泛应用和巨大潜力。展望未来,.NET将与新兴技术深度融合,拓展跨平台开发,推动云原生应用发展,持续创新。
28 4
|
27天前
|
机器学习/深度学习 人工智能 Cloud Native
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台
在数字化时代,.NET 技术凭借其跨平台兼容性、丰富的类库和工具集以及卓越的性能与效率,成为软件开发的重要平台。本文深入解析 .NET 的核心优势,探讨其在企业级应用、Web 开发及移动应用等领域的应用案例,并展望未来在人工智能、云原生等方面的发展趋势。
33 3
|
27天前
|
敏捷开发 缓存 中间件
.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素
本文深入探讨了.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素,并通过企业级应用和Web应用开发的实践案例,展示了如何在实际项目中应用这些模式,旨在为开发者提供有益的参考和指导。
24 3
|
27天前
|
开发框架 安全 Java
.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力
本文深入探讨了.NET技术的独特魅力与优势,涵盖高效的开发体验、强大的性能表现、高度的可扩展性及丰富的生态系统等方面,展示了其在软件开发领域的核心竞争力。.NET不仅支持跨平台开发,具备出色的安全性和稳定性,还能与多种技术无缝集成,为企业级应用提供全面支持。
29 3
|
3月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
46 7
|
3月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
74 0
|
4月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
55 0
|
4月前
|
开发框架 前端开发 安全
ASP.NET MVC 如何使用 Form Authentication?
ASP.NET MVC 如何使用 Form Authentication?
|
4月前
|
开发框架 .NET
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
142 0