.NET学习笔记(九) ------委托(下)

.NET中委托的性能演变 阅读详情

这一篇主要介绍委托的一些内部结构,想要了解委托的使用和功能可以看前一篇文章:.NET学习笔记(八) ------委托(上)

 前天不小心感冒了,吃了药但还是晕晕的,还是继续写把。。。

前面介绍了委托的功能和使用方法。委托实际是对一个函数指针的封装,那么他是如何指向一个函数,有是如何把多个方法都绑定起来的呢?

一 委托的内部结构

下面是简单的一个定义委托方法,写起来很简单,当编译器编译这句话的时候做了什么呢?

// 申明一个委托要绑定的方法签名
public  deletgate  void  ExampleDeletgate( int  x);

通过ILDASM我们可以看到,系统产生了以下代码:

// 构造器有2个参数为了方便后面使用,我重新定义这2个变量名字
// public ExamplDelegate(object target,int methodPtr)
.method  public  hidebysig specialname rtspecialname  
       instance 
void   .ctor( object   ' object ' , native  int   ' method ' ) runtime managed
{
}


// 下面两个是委托的一个异步回调用方法,我们暂时不关注他们
.method  public  hidebysig newslot  virtual  
        instance 
class  [mscorlib]System.IAsyncResult 
        BeginInvoke(int32 x,
class  [mscorlib]System.AsyncCallback callback, object   ' object ' ) runtime managed
{
}


.method 
public  hidebysig newslot  virtual  
        instance 
void   EndInvoke( class  [mscorlib]System.IAsyncResult result) runtime managed
{
}


// 这个方法和委托指定的方法原形是一样的,我同样改写下
// public void virtual Invoke(int32 x);
.method  public  hidebysig  virtual  instance  void  Invoke(int32 x) runtime managed
{
}

上面的代码有点乱,但是应该还是可以看出点头绪来。编译器在编译到这句的时候实际是产生了一个名字为ExampleDelegate的类,并且生成了4个方法。其中第一个是一个类型构造器,他需要2个参数。看到我重新命名的参数,大家应该猜测到他的作用了把。最后一个是一个Invoke方法,这个词是调用的意思。而且他的类型和申明的方法原形签名是相同的。大家也应该可以猜到。委托实际调用的是这个方法。而另外2个方法是和Invoke没什么区别,只是异步调用。后面文章会介绍异步调用的知识。

上面说了编译器的工作,下面我们具体来看下这个类,和其中的Invoke方法。ExampleDelegate成为了一个类,还记得定义委托对象是如何做的吗?

ExampleDelegate ed1 =   new  ExampleDelegate(Class.method) //实例方法
 
    ExampleDelegate ed2 = new ExampleDelegate(method) //静态方法

在定义一个ExampleDelegate类型的对象的时候,我们给他传递了一个方法。这里大家肯定觉得奇怪,上面的构造方法可是需要2个参数的。我们先看看这2个参数,target 是一个object对象,他表示帮定方法的对象。而method则是表示绑定的方法。编译的时候一个参数确实也通过了。这是因为编译器知道我们在构造一个委托。所以他会自动分析我们传递给他的方法的对象。

在ExampleDelegate类中有3个私有的成员变量,其中前两个提供了Target和Method 2个属性。我们可以通过这2个属性判断委托是否与一个方法绑定。

 看完了上面的3个字段应该就明白了,在定义一个委托的时候,我们的委托对象已经在内部记录了绑定的对象和要执行的方法。下面看下通过委托调用这个方法的情况

object  _target;   //指向绑定方法的对象,如果是实例方法则为调用方法的对象,若为静态方法则为空


MulticaseDelegate  _prev ;  //这也是一个委托类型,用与之向下一个委托,初始为null,在.net2.0中这个字段是object类型
int  _method,     //这个字段是从元数据中获得的一个值,改值是绑定的方法在元数据中的一个标识值

 

 

ed1(x);  // 通过委托调用绑定的方法

// 下面是ILDASM中看到的
 IL_000c:  stloc. 0
 IL_000d:  ldloc.
0
 IL_000e:  ldc.i4.
3
 IL_000f:  callvirt   instance 
void  delegateEx.Class1 / ExampleDelegate::Invoke(int32)   // 实际上是调用ExampleDelegate对象的Invoke方法
 IL_0014:  ret

看到编译后的代码实际是调用了内部的Inovke函数。当调用这个方法时,会用到_target和_method字段,这就让代理在指定的对象上调用期望的方法。

 

二 委托链

在前一片文章中,我们提到过委托链这个概念,而上面内部结构中有个_prev字段就是用来指向下一个委托对象的。这就使得委托可以指向其他对象,组成一个链表结构。

 在Delegate类中提供了几个静态方法,来往一个委托链上添家或移除委托对象。

public   static  Delegate Combine(Delegate a, Delegate b) {}

public   static  Delegate Combine( params  Delegate[] delegates) { }

public   static  Delegate Remove(Delegate source, Delegate value) { }
 
public   static  Delegate RemoveAll(Delegate source, Delegate value) { }

下面是操作的代码:

ExampleDelegate ed1 =   new  ExampleDelegate(method1) 
 
ExampleDelegate ed2 
=   new  ExampleDelegate(method2) 

    ExampleDelegate ed3 = new ExampleDelegate(method3) 

//把2个委托组成串
ExampleDelegate ed = (ExampleDelegate)Delegate.Combine(ed1,ed2);

    ed = (ExampleDelegate)Dleegati.Combine(ed,ed3);

要注意这里ed相当于链表的头接点,而我们插入的时候使用的是头插发,就是插入到头节点后面,而不是链尾巴。所以上面最后的结果是ed--> ed3-->ed2-->ed1-->null.委托链执行的时候仍旧是执行各个委托对象内部记录的方法,只是按顺序执行。下面就看下更具体的Invoke方法

public   void  Invoke( int  x )
{
  
if (_prve != null) _prve.Invoke(x);  //如果委托后面还有其他委托对象则执行下一个对象的Invoke方法

  _target.method(x);  
//如果委托后面没有其他委托对象,则通过内部的2个字段来执行期望的方法
}

可以看到Invoke内部是这样一个样子,所以实际上,方法是从委托链的末尾开始执行的。但要注意的是,如果委托的方法有返回值,那么只有最后一个执行的委托的值会被返回,而其他的委托的值都被丢弃。如何返回所有委托的值在后面会有介绍。

这里要注意的是当使用combine方法时,会构造一个新的委托对象,他的_target,_method字段和原委托相同,但_prve被重新设置。比如Combine(ed1,ed2);ed2会新建立一个委托对象来添加到委托链上,他的_prve指向ed1。因为委托对象一旦被构造就认为是恒定不变的,_prev =  null,不会改变。

关于委托比较:

所以2个ed2指向的不是同一个对象,通过ReferenceEquals方法可以看出来。这里简单介绍下委托对象的比较,委托MulticastDelegate类重写了Equals方法。在这个方法中,是通过比较委托对象的3个私有字段判断的,只有这3个字段全部相同时才相等。而在Delegate类中重写的Equals只比较了_target,_method2个字段。

下面看下把委托从委托链移除的例子

ExampleDelegate ed1 =   new  ExampleDelegate(method1) 
 
ExampleDelegate ed2 
=   new  ExampleDelegate(method2) 

// 把2个委托组成串
ExampleDelegate ed  =  (ExampleDelegate)Delegate.Combine(ed1,ed2);

// 移除
// 方法1:
// ExampleDelegate ed = (ExampleDelegate)Delegate.Remove(ed1,ed2);

// 方法2:
ExampleDelegate ed  =  (ExampleDelegate)Delegate.Remove(ed1, new  ExampleDelegate(method2) );

上面有2种方法,但第一种被注释掉了,因为他是错误的,而应该使用第2重,这看起来有些奇怪。但要记得前面说了委托的恒定性,委托一旦建立,他的_prev字段是无法修改的。所以如果你使用了第一种方法,那么ed2的_prev对象还是指向ed1的。所以,我们必须构建一个新的ed2对象,并且他的_prev =null,这样才是把ed2从委托链上移除了。

在移除过程中,Remove方法会扫描委托链,然后比较委托链上是否存在和新建的问题相同的委托。这里进行比较使用的是Delegate.Equals()方法,因为他只比较_target和_method两个字段(框架程序设计中译者写这里不是使用Delegate.Equals,而是使用的一个内部方法比较,但确实只比较这2个字段,我用Reflector看了下,方法如下:)

protected   virtual  Delegate RemoveImpl(Delegate d)
{
    
if ((this._target == d._target) && this.Method.Equals(d.Method))
    
{
        
return null;
    }

    
return this;
}

如果发现相同的委托,则移除这个委托,方法是修改这个委托前一个对象的_prev指针。如果找不到他也不会进行任何操作也不会返回异常。而remove每次只能移除一个委托对象。如果委托链上有2个ed2委托对象,必须使用两次remove。

注意:.net2.0中的委托链有所区别

在2.0中,委托有了一定的修改,上面介绍的是1.1的。但基本都是相同的,只是委托中的_prev字段发生了变化。在2.0中,这个字段成了Object类型,他不在是负责指向下一个委托,而是负责一个委托对象数组,通过这个数组来访问委托对象。

     

.net1.1中的委托链 (ed2,ed3应该指向新建构造的ed2,ed3两个对象)                                                                       .net2.0中的委托链

 

 从上面的图就可以看到双方的区别的,在2.0中_prev不在直接指向下一个委托对象,而是通过控制一个数组来实现。建立了ed他指向空,当把ed1加到链上时,直接用ed-->ed1,当把ed2加到链上时,发现已经有了一个委托对象,于是建立一个新的委托对象,并初始化他的3个字段,而他的_prev字段是一个对象数组,_prev[0]指向ed1,而_prev[1]指向ed2。当把ed3加到链上时,_prev一共指向3个对象了。ed指向新的委托对象。而之前的委托对象会被垃圾回收器回收掉。

这样的改进,访问时不需要遍历整个链,只需要遍历头结点的_prev数组。为什么怎么改进,我也不太清楚。

在C#中可以直接使用 +=,-=来操作委托链。前面的示例中就可以看到了。因为C#中这2个操作符号进行了重载,可以通过ILDASM工具查看。另外在.net2.0中c#还提供了一些使用委托上的便利,比如匿名方法,这里就不在详细说明了。

 

三 对委托进行更多的控制

从前面可以看到,在访问委托链的时候,都是遍历链,按照顺序来访问,如果其中一个委托发生错误,就会影响后面的委托对象。而且只返回最后一个委托对象的值。

当然我们可以自己来显式的访问每个委托对象,而访问之前,我们必须获得链上所有的委托对象。因为委托的_prev是一个私有字段,所以我们想操作一个链表一样来访问每个对象,但可以使用MulticastDelegate提供的一个获得链中的所有委托

// 获得一个委托数组,每个元素是ed链中的委托
Delegate arrayofDelegate  =  ed.GetInvocationList();

foreach (ExampleDelegate eds  in  arrayofDelegate )
{
    eds(
10); //显示的调用委托,可以通过控制语句进行其他控制
}

这样,当有委托发生异常时,可以进行处理,保证其他委托正常运行,而且可以获得每个委托返回的值(如果有返回值)

关于事件中的委托:

时间和委托是联系最紧密的,前面我们也说了,事件模型,是通过委托来实现的。消息发布者和订购者都是通过委托来联系的。但是不同的是,在定义委托对象时,加入了event 关键字。这个关键字使得委托的对象在创建被定义为了私有类型,也就是不能象这里,直接对委托对象进行操作。而只能使用+=,-=两个重载的操作符,来操作委托链。这样就避免的对委托的错误操作。其实这个也可以看做是对委托的一种控制。

 

四 总结

通过上面的讲解,对委托的内部结构和实现应该有了一个比较清楚的认识。委托实际是对一个函数指针的封装,通过一个链,把多个委托连接起来。就好象链表一样。委托的用途很广泛,无论是事件,回调函数还是异步编程。而且使用委托也是降低模块间耦合性的一个办法。当然还可以通过接口等其他方法来实现其中一些功能。所以理解委托是十分有必要的。自己也只是了解了一些以后,写成笔记和大家分享,有很多东西也不知道,所以无法说的太深,有任何错误和不恰当的地方也希望大家指出。

.Net委托详解 委托是.NET中一个非常有用的特性,它提供了回调方法、事件处理等多种用途的实现机制。理解并熟练使用委托,可以使代码更加灵活和强大。 阅读详情

相关推荐

实战指南:基于华为Ascend NPU的大模型W8A8量化调优与精度提升

本文提供了一份基于华为Ascend NPU进行大模型W8A8量化的实战调优指南。详细介绍了从环境搭建、使用msmodelslim框架进行基础量化,到通过离群值抑制、校准集优化和量化回退等关键技术提升精度的全流程。旨在帮助开发者在华为NPU硬件上实现模型推理的显著加速,同时有效控制精度损失。

weixin_29227425的博客 271

Delegate.Combine

今天看到了Delegate.Combine静态方法,就随手测试了下。本以为只要是参数和返回类型相同的 就可以了,如下所示Delegate d3 = Delegate.Combine(newtext1(method1), newtext2(method2));结果报错, “委托必须具有相同的类型。”将两个参数都改为text1后运行正常,public delegate void ...

weixin_33725126的博客 480

从零到一:手把手教你用Verilog在FPGA上构建自己的FFT处理器(不依赖IP核)

本文详细介绍了如何从零开始使用Verilog在FPGA上构建256点FFT处理器,不依赖商业IP核。内容涵盖FFT算法基础、蝶形运算单元设计、整体架构实现、时序收敛优化策略以及测试验证方法,重点提升FPGA上算法部署的运行效率与资源利用率。

vv45678的博客 821

[C#] 委托与事件

首先,本小节我们来介绍一下委托最最基础的部分,在列举这些基础知识之前,我们先从实例出发看看为什么要使用委托,以及什么情况下需要使用委托。 1. 为什么要使用委托? 假设我们有一个这样的需求,写一个MakeGreeting函数,这个函数在被调用的时候需要告诉它两点:跟谁greet、怎么greet。 我们的第一反应可能是,很简单呀,给这个函数传两个参数,就传跟谁greet和怎么greet。如果怎么greet只是一个string,当然可以这样做,可万一它们没那么简单呢? 继续假设,假设怎么greet只有两种情

pragma_g的博客 584

鸿蒙5应用真机调试超详细教程

本文详细介绍了鸿蒙5应用的真机调试全流程,包括开发环境搭建(安装DevEcoStudio、配置SDK)、真机调试准备(开启USB调试、配置自动/手动签名)、调试实战(生成HAP包、断点调试技巧)以及多设备协同调试方法。文中提供了设备连接、签名配置等常见问题的解决方案,并包含示例代码展示分布式设备联动功能。通过本教程,开发者可快速掌握鸿蒙5应用的调试技能,建议结合官方文档深入学习高级调试技巧。

2301_79392153的博客 2196

如何制作Mike21溢油模型围油栏文件

这段时间群友在做海洋环评的做了一个MIKE21的溢油模型,溢油模型其实也是ECOLAB模块的应用,而在海上发生溢油事件的时候,为防止溢油对海洋生态的破坏,经常使用的一种手段就是使用围油栏技术将溢油控制在一定范围并进行处理。今天小编就给大家说说在MIKE21里怎么实现围油栏文件的制作

zhuzhujiayoua的博客 1329

C#委托链

使用Delegate.Combine时,注意两点: 1. 不可以将不同签名的两个委托相互Combine。 2.如果将有返回值的两个委托A 和 B Combine,那么返回值是最后一个委托的的返回值,也就是B委托的值 转载于:https://www.cnblogs.com/leiGameDesigner/p/9269166.html...

weixin_30576827的博客 229

SUMO仿真教程(5) —— 使用“XML“语言自定义构建路网

文章目录一.简要介绍1.node file2.edge file3.lane definitions(1)路段细分(2)邻近的对向车道(3)删除边或车道4.type file(1)简要概述(2)edge定义中引用type文件的示例(3)指定车辆种类的速度限制5.connections file(1)简要概述:(2)connection的属性参数(3)删除连接(4)设置连接的优先级(5)同一边的多个连接二.演示示例:1.自定义编写node file2.自定义编写edge file3.自定义编写type fil

weixin_50632459的博客 5015

C#委托学习(三):委托链—同时委托多个方法

上一节中介绍了下编译器是如何来翻译委托的,从中间语言的角度去看委托,希望可以帮助大家进一步的理解委托,然而之前的介绍都是委托只是封装一个方法,那委托能不能封装多个方法呢?因为生活中经常会听到,我代表大家的意见等这样的说话,既然委托也是一个代表,那他如果只能代表一个人,那他的魅力就不是很大了吧,所以我们就会委托能不能代表多个方法的? 答案是可以的,这就是本节要讲的内容——委托链,委托链也是一个委托,

Sayesan的专栏 8113

AI应用架构师实战:超算中AI与量子计算融合的初探与架构

当大模型的算力需求突破E级超算的极限,当量子计算的“量子优势”从实验室走向真实场景,超算+AI+量子计算的融合架构成为解决复杂问题的关键路径。本文从架构师的实战视角出发,系统拆解三者融合的底层逻辑:从“计算本质”的第一性原理推导,到“量子-经典异构”的架构设计;从“量子机器学习”的代码实现,到“金融/医药”的场景落地。我们将回答:如何用超算支撑量子计算的噪声抑制与纠错?如何用量子计算加速AI模型的训练与推理?如何设计可扩展、高可用的融合系统?最终给出架构师的实战指南——从技术选型到运营管理的全流程方法论。

AIGC应用创新大全的博客 924

【经验&技巧】如何在ADS中导入示波器的时域波形?

从示波器中导出的时域波形数据,需要按照固定的格式进行修改,并通过Display dataset对话框导入ADS。

一只豌豆象的博客 1572

C#--委托(Delegate)和事件(Event)

委托在本质上仍然是一个类,我们用delegate关键字声明的所有委托都继承自System.MulticastDelegate。后者又是继承自System.Delegate类,System.Delegate类则继承自System.Object。委托是一种类型安全的函数回调机制, 它不仅能够调用实例方法,也能调用静态方法,并且具备按顺序执行多个方法的能力。 1. 委托也好,事件也好最初的起源是C/C...

qq826364410的专栏 854

【2026年华为暑期实习(非AI方向(通软&嵌软&测试&算法&数据科学))-4月8日-第一题- 包裹的编码】(题目+思路+Java&C++&Python解析+在线测试)

摘要:该问题要求将给定的十进制整数N转换为混合进制编码字符串,并处理回文检测。首先根据N的符号位确定编码首位(0或1),然后按输入的进制序列依次对N的绝对值进行取余和整除操作,得到编码数组。将数组元素转换为字母后生成字符串,若字符串为回文则添加"(palindrome)"后缀;否则输出最长回文子串(字典序最小)。算法采用中心扩展法检测回文,时间复杂度为O(L²),空间复杂度为O(L),其中L为字符串长度。

m0_73659489的博客 129

VB.net学习笔记(九)委托

Module Sort '声明委托。类似C++的函数指针类型 Public Delegate Function Compare(ByVal v1 As Object, ByVal v2 As Object) As Boolean '...... End Module Public Shared Function

白话魔法师 1万+

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

VB.NET学习笔记:初识委托——System.Delegate 类

想必你对生活中的“委托”耳闻能详,如委托某人办某事。没想到VB.NET编程也要跟委托打交道。因扩展控件,使其列头增加全选全不选复选框并具备分页功能需要用到委托和事件,详见博文《》、《》,所以拜读了多篇相关委托与事件的博文,结合自己在编程中的使用情况,谈谈我对委托与事件的一些认识,记录下来做个记号,温习时可以用用。 一、委托 一、问题暴露:方法能作为参数传给方法吗? 为了优化精简代码,通常会把多次重...

zyjq52uys的博客 2211

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

VB.NET学习笔记:再谈委托——同步、异步、Lambda 表达式和内置委托

由于近期在研究防止窗体假死该如何给长时间运行的方法加一个等待的画面,需要用到异步委托和Lambda 表达式,所以紧急饿补了相关内容,现把学习感受记录备查。 相关博文:《异步委托实现等待窗体(loading界面),执行任务超时可以取消操作》 本文主要是简化《程序长时间执行任务时窗体会失去响应造成假死避免重复点击按钮的解决思路》一文代码,更突出问题。 一、窗体假死 新建一个windows窗体应用程序,...

zyjq52uys的博客 3388

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

.NET 学习笔记——委托

.NET 学习笔记——委托 一、委托 委托是引用类型,因此委托有引用和对象。 (1) 从数据结构来讲,委托是和类一样是一种用户自定义类型。 (2) 从设计模式来讲,委托(类)提供了方法(对象)的抽象。 委托是方法的抽象,它存储的就是一系列具有相同签名和返回回类型的方法的地址。调用委托的时候,委托包含的所有方法将被执行。 delegate void Mydel(int x) Mydel mydel; mydel = new Mydel(demo.printlow) //创建委托并保存使用 mydel

qq_42405977的博客 322

VB.NET 委托 Delegate Action Func

VB.NET 委托 :Delegate、 Action、 FuncDelegateActionFunc实例参考资料 委托,是CTS(公共类型系统)规定的5种类型之一(类类型、结构类型、接口类型、枚举类型、委托类型)。它能够调用对象的方法(实例方法)和类的方法(静态方法、在VB.NET里的Shared方法)。实现间接访问某一封装的函数方法,始终明确,委托可被视作类 Delegate Delegate 是委托的祖宗,Action和Func是VB.NET简化的委托。 委托实现的步骤: 1. 创建委托(相当于创建类

SZF 3695

.NET 中的委托

1.1.1定义   委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和返回值,如下面的示例所示:   //Code in C#   public delegate int PerformCalculation(int x, int y);   与委托的签名(由返回类型和参数组成)匹配的任何方法都可以分...

weixin_34252686的博客 642

vb.net中的委托与事件

委托是CTS(公共类型系统)规定的5种类型之一(类类型、结构类型、接口类型、枚举类型、委托类型)它是一种类型可以用来调用其他对象的方法,也称为函数指针。其实在vb.net中委托也可以当做是可以用来共享其他对象的方法的对象。当程序必须通过调用一个方法来执行某个操作(调用某个方法),但在编译时不知道该方法是什么时,就可以使用委托。委托允许在程序运行时指定调用的方法,委托的特点是面向对象的,类型是安全的

不忘初心 ,方得始终 1万+

C#委托之如何理解委托面试常见题:

委托(delegate)是一种存储函数引用的类型。这听起来相当深奥,但其机制是非常简单的。委托的声明非常类似于函数,但不带函数体,且要使用delegate 关键字。委托的声明制定了一个返回类型和一个参数列表。 定义了委托后,就可以声明该委托类型的变量。接着把这个变量初始化为与委托具有相同返回类型和参数列表的函数引用。之后,就可以使用委托变量调用这个函数,就像该变量是一个函数一样。 有了引用函数的变...

qq_41231360的博客 3204

【.NET Core】委托(Delegate)应用详解

委托(Delegate)是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。委托(Delegate)类似于C或C++中函数指针。委托是将方法调用者和目标方法动态关联起来,委托是一个类,实质上是一个类,可以通过委托隐藏方法,虽然委托定义方法的参数及其返回值,但是它并不是和方法一个层级的。委托(Delegate)可以将方法当作另一个方法的参数来进行传递,这种方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。delegate。

记录总结工作过往 3091

.Net 委托探秘

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。.Net 中通过委托提供了回调函数的机制。

Qanx的博客 765

.Net 委托

委托使代码更加灵活,允许在运行时动态地改变方法的调用。使用委托可以减少代码之间的耦合度。

qq_44230029的博客 562
上一篇: .NET学习笔记(八) ------委托(上)
下一篇: J2EE系统结构概念
cc_net
博客等级 码龄21年 901粉丝 54原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值