一. 委托的分类

通过用什么类型的方法来声明为委托,可以分为两类:

1. 委托静态方法:把一个静态方法给委托

2. 委托实例方法:把一个实例对象的成员方法给委托

(这两个名字是博主取的,可能不是很专业只是为了好区分)

二. 原理部分

委托是将函数指针和实例对象打包在一起的类,它有两个重要的成员,一个用来保存实例对象,一个用来保存函数的指针。从源码中我们可以查看System.Delegate,如下:

1. 将会调用方法所在的对象

// _target is the object we will invoke on
[System.Security.SecurityCritical]
internal Object _target;

2. 将会调用的方法指针

// _methodPtr is a pointer to the method we will invoke
// It could be a small thunk if this is a static or UM call
[System.Security.SecurityCritical]
internal IntPtr _methodPtr;

另外,我们查看System.Delegate的属性,我们可以看到一个属性 Target

public Object Target
{
get
{
return GetTarget();
}
}

来看一下这个 GetTarget() 方法的功能

[System.Security.SecuritySafeCritical]
internal virtual Object GetTarget()
{
return (_methodPtrAux.IsNull()) ? _target : null;
}

可以看到这边有一个字段 _methodPtrAux,这是一个IntPtr类型的指针,可以看到注释可以看出,当把一个静态方法给委托的时候,将会返回一个 null,如果是一个实例方法的时候,将会返回当前方法所在的实例对象(this)

// In the case of a static method passed to a delegate, this field stores
// whatever _methodPtr would have stored: and _methodPtr points to a
// small thunk which removes the "this" pointer before going on
// to _methodPtrAux.
[System.Security.SecurityCritical]
internal IntPtr _methodPtrAux;

三. 测试代码

测试类 Test.cs:

public class Test
{
/// <summary>
/// 实例方法
/// </summary>
public void ShowHelloWorld1()
{
Console.WriteLine("Hello World! -- 1");
} /// <summary>
/// 静态方法
/// </summary>
public static void ShowHelloWorld2()
{
Console.WriteLine("Hello World! -- 2");
}
}

委托声明:

public delegate void ShowHelloWorldMethod();

上端测试代码:

//声明测试对象
Test test = new Test(); //构造实例方法的委托
ShowHelloWorldMethod del = test.ShowHelloWorld1; //判断一下Target是不是指向方法所在的对象
Console.WriteLine(del.Target is Test);//True //调用一下
((Test)del.Target).ShowHelloWorld1();//Hello World! -- 1 //构造静态方法的委托
ShowHelloWorldMethod del2 = Test.ShowHelloWorld2; //判断一下Target是不是null
Console.WriteLine(del2.Target == null);//true

测试结果符合我们的预期:

四. 总结

如果委托的Target属性为null说明是静态方法的委托,如果委托的Target属性不为null说明是实例方法的委托。

C#如何判断委托是实例方法还是静态方法的更多相关文章

  1. 关于python的类方法、实例方法和静态方法区别

    python的类方法需要在方法前面加装饰器:@classmethod ,静态方法是在方法前面加装饰器:@staticmethod. 类方法.类属性是属于类自身,属于类自身的命名空间,和实例方法.实例属 ...

  2. Python高级笔记(五)--实例方法、静态方法和类方法

    1. 类属性.实例属性 类属性在内存中只保存一份 实例属性在每个对象中都要保持一份 obj.__class__.country="xxx": 可以修改类属性 2. 实例方法.静态方 ...

  3. Python类变量,实例变量,类方法,实例方法,静态方法的分析

    Python作为动态语言,跟静态语言如c/c++有很大区别,其中的一个重要的特性就是Python的变量无需声明直接可用.同样,类的成员变量无需声明,直接可用.目的是为了动态语言跟灵活,在思路想到的时候 ...

  4. python3类方法,实例方法和静态方法

    今天简单总结下python的类方法,实例方法,静态方法. python默认都是实例方法,也就是说,只能实例对象才能调用这个方法. 那是不是说类方法也只能被类对象本身来调用呢,当然,不是.类方法既可以被 ...

  5. Python Class 的实例方法/类方法/静态方法

    实例方法.类方法.静态方法 class MyClass(object): class_name = "MyClass" # 类属性, 三种方法都能调用 def __init__(s ...

  6. [Python3 填坑] 017 实例方法、静态方法、类方法的区别

    目录 1. print( 坑的信息 ) 2. 开始填坑 2.1 先上例子 2.2 分析 1. print( 坑的信息 ) 挖坑时间:2019/04/07 明细 坑的编码 内容 Py024-1 实例方法 ...

  7. 面向对象~~类的成员: 私有成员,公有成员, 实例方法, 类方法, 静态方法, 属性(property), isinstance ,issubclass, 元类(type)

    一 私有成员公有成员 公有成员: 在任何地方都能访问 私有成员: 只有在类的内部才能访问 类从加载时,只要遇到类中的私有成员,都会在私有成员前面加上_类名 二 实例方法 实例方法就是类的实例能够使用的 ...

  8. Python绑定方法,未绑定方法,类方法,实例方法,静态方法

    >>> class foo(): clssvar=[1,2] def __init__(self): self.instance=[1,2,3] def hehe(self): pr ...

  9. python中的实例方法、静态方法、类方法、类变量和实例变量

    class MyTest: myname = 'peter' # add a instance attribute    def __init__(self, name):        self.n ...

随机推荐

  1. WinForm GroupBox控件重绘外观

    private void groupBoxFun_Paint(PaintEventArgs e, GroupBox groupBox){ e.Graphics.Clear(groupBox.BackC ...

  2. 《Java Spring框架》SpringXML配置详解

    Spring框架作为Bean的管理容器,其最经典最基础的Bean配置方式就是纯XML配置,这样做使得结构清晰明了,适合大型项目使用.Spring的XML配置虽然很繁琐,而且存在简洁的注解方式,但读懂X ...

  3. sql语句字符串包含

    select instr('1222','122') from dual//前者包含后者>0 oracle mysql 数据库可中 select charindex('1','12') from ...

  4. 使用littlefs-fuse在PC端调试littlefs文件系统

    背景 littlefs是arm面向嵌入式设备推出的一款掉电安全的小型文件系统,具有抗掉电,动态磨损均衡,RAM/ROM需求少等特点,具体介绍可见 https://github.com/ARMmbed/ ...

  5. Docker从入门到掉坑(四):上手k8s避坑指南

    在之前的几篇文章中,主要还是讲解了关于简单的docker容器该如何进行管理和操作,在接下来的这篇文章开始,我们将开始进入对于k8s模块的学习 不熟悉的可以先回顾之前的章节,Docker教程系列文章将归 ...

  6. alibaba/flutter_boost

    flutterBoost使用笔记 新一代Flutter-Native混合解决方案. FlutterBoost是一个Flutter插件,它可以轻松地为现有原生应用程序提供Flutter混合集成方案.Fl ...

  7. mysql-5.7.21-winx64安装教程

    1 . 下载对用的版本信息 地址是:https://dev.mysql.com/downloads/mysql/ 2 . 解压到目录 D:\tools\mysql\mysql-5.7.21-winx6 ...

  8. 算法设计与分析——n后问题(回溯法+位运算)

    一.问题描述 在n×n格的国际象棋上摆放n个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 二.算法设计 解n后问题的回溯算法描述如下: #include ...

  9. 数据库学习笔记day04

    --row_number()over(partition by xxx order by xxx)分组排序函数 特点:组内连续且唯一select ename,sal,deptno,row_number ...

  10. Android 非法字符:'/ufeff'

    [问题来源] 不知道大家有没有做过这样的事,在Android开发的过程中,通过文本直接修改代码,不打开编译器,然后提交让同时编译运行.这时Android编译就会报错,指定修改的文件开始位置,显示非法字 ...