title author date CreateTime categories
C# 在 构造函数添加 CallerMemberName 会怎样
lindexi
2019-05-21 11:28:32 +0800
2019-1-2 19:6:44 +0800
C#

在 C# 中有一个特性 CallerMemberName 可以给方法知道调用这个方法的方法名,在 UWP 中用这个特性很多,特别是在使用 MVVM 绑定

如果在构造函数使用这个特性会发生什么?

构造函数可能是方法调用,可能是反射调用,可能是基类使用,这些使用的值是什么?

先定义一个类

    public class F1
{
/// <inheritdoc />
public F1([CallerMemberName] string name = "")
{
Debug.WriteLine(name);
}
}

小伙伴都知道,下面的代码会输出 Foo 因为在这个方法调用

        public MainWindow()
{
InitializeComponent(); Foo();
} private void Foo()
{
new F1();
}

在方法调用的时候,小伙伴都知道 CallerMemberName 能拿到调用的方法,在 .NET 4.5 之后提供的这个特性实在好用,通过这个特性就可以在参数传入调用的方法,同时因为这个特性是在编译时添加的,所以比反射快很多。

但是如果再添加一个类 F2 继承 F1 会出现什么?

        public MainWindow()
{
InitializeComponent(); new F2();
} public class F2 : F1
{
/// <inheritdoc />
public F2()
{
}
}

现在运行代码,发现这个值居然是空

但是如果此时修改 F2 函数,这时输出的就是 .ctor 因为 CallerMemberName 是编译做的

    public class F2 : F1
{
/// <inheritdoc />
public F2() : base()
{
}
}

分析一下两个的 IL 代码就知道,在 public F2() : base() 的 IL 代码

  .method public hidebysig specialname rtspecialname instance void
.ctor() cil managed
{
.maxstack 8 // [50 23 - 50 29]
IL_0000: ldarg.0 // this
IL_0001: ldstr ".ctor" // 压入字符串 .ctor 然后调用 F1 的构造函数
IL_0006: call instance void lindexi.F1::.ctor(string)
// 在这个构造函数传入刚才压的字符串,也就是 F1(".ctor") 在 F1 的 name 就是这里传入的字符串 IL_000b: nop // [51 9 - 51 10]
IL_000c: nop // [52 9 - 52 10]
IL_000d: ret }

public F2() 的 IL 代码其实几乎没有多少修改

  .method public hidebysig specialname rtspecialname instance void
.ctor() cil managed
{
.maxstack 8 // [50 9 - 50 20]
IL_0000: ldarg.0 // this
IL_0001: ldstr "" // 只有这句和上面不同,传入的是空所以在 F1 收到的值就是这里传入
IL_0006: call instance void lindexi.F1::.ctor(string)
IL_000b: nop // [51 9 - 51 10]
IL_000c: nop // [52 9 - 52 10]
IL_000d: ret }

可以看到虽然调用的方法看起来是相同的,但是运行的结果是不相同的,因为 CallerMemberName 是在编译时做的

从上面的 IL 也可以看到 CallerMemberName 是在编译的时候传入的值,性能会比反射快,如果需要获得调用这个方法的方法的方法,也就是 A 调 B 然后 B 调 C 需要在 C 里面知道 A 是哪个,就需要使用 WPF 判断调用方法堆栈

2019-5-21-C#-在-构造函数添加-CallerMemberName-会怎样的更多相关文章

  1. C# 在 构造函数添加 CallerMemberName 会怎样

    在 C# 中有一个特性 CallerMemberName 可以给方法知道调用这个方法的方法名,在 UWP 中用这个特性很多,特别是在使用 MVVM 绑定 如果在构造函数使用这个特性会发生什么? 构造函 ...

  2. 2019.3.18考试&2019.3.19考试&2019.3.21考试

    2019.3.18 C O D E T1 树上直接贪心,环上for一遍贪心 哇说的简单,码了将近一下午终于码出来了 感觉自己码力/写题策略太糟糕了,先是搞了一个细节太多的写法最后不得不弃疗了,然后第二 ...

  3. 2019.04.21 python核心特征

    本阶段我们将了解Python是如何管理内存的,学习内存管理让我们掌握python的运行机制: 并且在python中有许多函数式编程的特性,比如闭包,装饰器和生成器,这些都是一些比较难掌握的概念,但面试 ...

  4. 2019.03.21 admin

    1.新建文件创建一个应用类 stu Python manage.py startapp stu 2,创建应用类 记得在setting中的installed_apps中添加应用 student/mode ...

  5. 2019.01.21 bzoj2441: [中山市选2011]小W的问题(树状数组+权值线段树)

    传送门 数据结构优化计数菜题. 题意简述:给nnn个点问有多少个www型. www型的定义: 由5个不同的点组成,满足x1<x2<x3<x4<x5,x3>x1>x2 ...

  6. 给Date的构造函数添加属性和方法

    let d = Date.prototype; Object.defineProperties(d, { 'year': { get: function () { return this.getFul ...

  7. 2019.10.21 csp-s模拟测试81 反思总结

    T1: 把每一行状压,按行DP.设fi,j,k,i表示第几行,j是当前行的1覆盖状态,k是当前行选择按钮的状态.转移的时候枚举j和k,再枚举下一层的按钮选择情况l.如果l和j可以全覆盖当前层则转移合法 ...

  8. 2019.2.21 T2题解

    meet 大概思路就是 , 找出相交的路径 , 判断方向 , 分类讨论.. 假设已经找出了相交路径 ... 若方向相同 , 则找到相交路径上边权的最大值 , 若最大值>出发时间差 , 则可行. ...

  9. Vue集成tinymce富文本编辑器并实现本地化指南(2019.11.21最新)

     tinymce是一款综合口碑特别好.功能异常强大的富文本编辑器,在某些网站,甚至享有"宇宙最强富文本编辑器"的称号.那么,在Vue项目中如何集成呢?这并不困难,只需要参照官方教程 ...

随机推荐

  1. The linux command 之定制提示符

    一.提示符分解 默认提示符如下所示: [me@linuxbox ~]$ 可以看出它包括我们的用户名.主机名.当前工作目录.提示符是由PS1变量定义的. [me@linuxbox ~]$ echo $P ...

  2. BZOJ 1084 (SCOI 2005) 最大子矩阵

    1084: [SCOI2005]最大子矩阵 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 3560 Solved: 1779 [Submit][Sta ...

  3. windows下,根据端口号杀死进程

    1.cmd下,根据端口号查询进程号 C:\>netstat -ano|findstr " 2.根据进程号928,在任务管理器杀死PID为928进程 注意:默认情况下,进程选项卡里没有P ...

  4. How to Hide Apache Tomcat Version Number from Error Pages

    1. 进入tomcat lib目录 cd /usr/local/tomcat7/lib 2. 解压catalina.jar jar xvf catalina.jar 3. 修改ServerInfo.p ...

  5. hysbz3676 回文串 回文自动机

    回文自动机模板题 头铁了一下午hdu6599,最后发现自己的板有问题 先放这里一个正确性得到基本确认的板,过两天肝hdu6599 #pragma GCC optimize(2) #include< ...

  6. Font Awesome 完全兼容 Bootstrap 的所有组件。

    "F_FullName": "其他", "F_Icon": "glyphicon glyphicon-backward fa-lg ...

  7. 注解@Qualifier@Primary

    在Controller中需要注入service那么我的这个server有两个实现类如何区分开这两个impl呢 根据注入资源的注解不同实现的方式有一点小小的区别 在Controller中使用 @Auto ...

  8. LINUX挂接光盘镜像文件

    1.从光盘制作光盘镜像文件.将光盘放入光驱,执行下面的命令. #cp /dev/cdrom /home/sunky/mydisk.iso 或 #dd if=/dev/cdrom of=/home/su ...

  9. 2、docker镜像管理

    Docker镜像管理 镜像是Docker容器的基础,想运行一个Docker容器就需要有镜像.我们上面已经学会了使用search搜索镜像.那么这个镜像是怎么创建的呢? 创建镜像 镜像的创建有以下几种方法 ...

  10. PCA降维的前世今生

    PCA降维的数学原理 PCA(Principal Component Analysis)是一种常用的数据分析方法.PCA通过线性变换将原始数据变换为一组各维度线性无关的表示,可用于提取数据的主要特征分 ...