今天来玩一点变态的,使用反射获取到某个类型的构造函数,接着多次对此类型的某个对象调用构造函数方法。请问此时会发生什么

假定有一个类型 Foo 的定义如下

        class Foo : IDisposable
{
public Foo()
{
} public int F1 { set; get; }
public int F2 { set; get; } = 10;
}

先使用 RuntimeHelpers 的 GetUninitializedObject 方法创建对象而不调用构造函数

        var foo = (Foo) RuntimeHelpers.GetUninitializedObject(typeof(Foo));

如果给 Foo 的构造函数添加断点,那么在运行上面代码的时候,可以看到断点是不会进入。详细请看 dotnet C# 只创建对象不调用构造函数方法

此时虽然 Foo 对象 foo 创建了,但是此对象还没有经过构造函数。接下来咱给此对象赋值,请看代码

                var foo = (Foo)RuntimeHelpers.GetUninitializedObject(typeof(Foo));
foo.F1 = 2;
foo.F2 = 2;

请问此时的 Foo 里面的 F1 和 F2 属性分别是什么?当然就是 2 了

那如果用反射取出构造函数,对 foo 对象调用构造函数呢

                var constructorInfo = typeof(Foo).GetConstructor(new Type[0]);
constructorInfo!.Invoke(foo, null);

此时可以看到 foo 对象里面,两个属性的值不同。具体是啥?自己去本文末尾拉代码跑跑看

接着再给 foo 对象赋值,如下面代码

                foo.F1 = 5;
foo.F2 = 5;

然后再次调用构造函数,如下面代码

                foo.F1 = 5;
foo.F2 = 5;
constructorInfo!.Invoke(foo, null);

请问此时的 F1 和 F2 属性的值是什么?

回顾一下基础知识,在类里面写的 public int F2 { set; get; } = 10; 代码其实是 C# 语言带来的功能,在构建的时候,会被转写为大概如下的构造函数代码

            public Foo()
{
F2 = 10;
}

通过 IL 代码可以看到实际的逻辑如下

    .method public hidebysig specialname rtspecialname instance void
.ctor() cil managed
{
.maxstack 8 // [53 43 - 53 45]
IL_0000: ldarg.0 // this
IL_0001: ldc.i4.s 10 // 0x0a
IL_0003: stfld int32 KicheyurcherNiwhiyuhawnelkeera.Program/Foo::'<F2>k__BackingField' // [48 13 - 48 25]
IL_0008: ldarg.0 // this
IL_0009: call instance void [System.Runtime]System.Object::.ctor()
IL_000e: nop // [49 13 - 49 14]
IL_000f: nop // [50 13 - 50 14]
IL_0010: ret } // end of method Foo::.ctor

在 C# 中,其实构造函数也是一个函数而已,如上面代码,只有写给 F2 赋值的逻辑,而没有给 F1 赋值的逻辑。因此在调用构造函数的时候,只会改变 F2 属性的值,而不会更改 F1 属性的任何值。也因为构造函数只是一个函数,因此调用多次就和调用一个方法多次是一样的

本文所有代码放在githubgitee 欢迎访问

可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 5eb2ea112f2861791fafda9ed326657fd05572dd

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

获取代码之后,进入 KicheyurcherNiwhiyuhawnelkeera 文件夹

dotnet C# 多次对一个对象调用构造函数会发生什么的更多相关文章

  1. [C++基础]在构造函数内部调用构造函数

    看下面的面试题: #include <iostream> using namespace std; struct CLS { int m_i; CLS( int i ) : m_i(i){ ...

  2. 为什么字符串类型可以调用构造函数String的方法,却又不是它的实例

    从所周知,在js中定义一个字符串我们有两种办法: var a = new String("a"); var a = "a"; 第一种方法使用构造函数创建,作为S ...

  3. 转:C++何时调用构造函数,何时调用析构函数

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/wjf1997/article/detai ...

  4. java静态方法调用&&构造函数&&静态块

    静态方法,也就是使用static声明的方法,在虚拟机启动加载类的时候就进行了创建,所以使用到静态方法时,直接使用类名点静态方法即可调用.java在执行静态方法前,不会调用构造函数:构造函数是在实例化j ...

  5. c++ 对象复制引用时何时调用构造函数、析构函数

    class TEST{ private : public : TEST() {std::cout << "constructor" << std::endl ...

  6. c++构造函数中调用构造函数---匿名对象再探

    #include<iostream> #include<string> using namespace std; class Copy_construction { publi ...

  7. javaScript 调用构造函数 Array() 时没有使用参数, length总是0

    如果调用构造函数 Array() 时没有使用参数,那么返回的数组为空,length 字段为 0. 当调用构造函数时只传递给它一个数字参数,该构造函数将返回具有指定个数.元素为 undefined 的数 ...

  8. Java构造函数中调用构造函数

    在Java中,当为一个类创建了多个构造函数时,有时想在一个构造函数中调用另一个构造函数以减少代码量.这时可以使用this关键字来实现. 通常,当使用this关键字时,它意味着"这个对象&qu ...

  9. 牛客网Java刷题知识点之构造函数可以调用一般函数,但是一般函数不可以直接调用构造函数

    不多说,直接上干货! 通过 牛客网Java刷题知识点之构造函数是什么.一般函数和构造函数什么区别呢.构造函数的重载.构造函数的内存图解 我们对构造函数有了一个比较清楚的认识,当我们在创建对象时,我们会 ...

  10. C# this调用构造函数及析构函数

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace trai ...

随机推荐

  1. 一文讲透Java核心技术之高可扩展利器SPI

    大家好,我是冰河~~ SPI的概念 JAVA SPI = 基于接口的编程+策略模式+配置文件 的动态加载机制 SPI的使用场景 Java是一种面向对象语言,虽然Java8开始支持函数式编程和Strea ...

  2. python 图片转文字小工具

    应群友要求,要做一个图片转文字的格式,因为有些人的简历中只有一张图片要提取他里面的文字就不好办了. 于是就有了下面这个小工具: 功能:选择要识别的图片后,识别出来后存到.txt文本中. 实现原理,基于 ...

  3. C# AES CBC模式 加密和解密

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.S ...

  4. 终于来了!FastGPT 正式兼容 GPT 应用

    终于来了!FastGPT 正式兼容 GPT 应用 FastGPT V4.7 正式加入了工具调用功能,可以兼容 GPTs 的 Actions.这意味着,你可以直接导入兼容 GPTs 的 Agent 工具 ...

  5. kafka集群启动命令脚本文件kf.sh

    注意代码缩进 添加执行权限 chmod +x kf.sh 1 #! /bin/bash 2 case $1 in 3 "start"){ 4 for i in hadoop102 ...

  6. Spring框架之IoC( Inversion of Control )基础知识入门

    1.IoC创建对象的方式 使用无参构造创建对象 假如要使用有参构造创建: 下标赋值constructor-arg <!--有参--> <bean id="User" ...

  7. 3D Object Detection Essay Reading 2024.04.05

    EMIFF 论文:https://arxiv.org/abs/2303.10975 代码:https://github.com/Bosszhe/EMIFF ​ 本文提出了一种新的基于摄像机的三维检测框 ...

  8. #线段树、树状数组#D 筹备计划

    分析 首先这个位置应该是带权中位数\((\geq \frac{sum+1}{2}(奇数要加一,WA了几次了))\),但是既然有这个选择的限制, 那么要用线段树求出可选择的前驱和后继,然后用树状数组计算 ...

  9. Go 语言 Printf 函数和格式化动词详解

    Printf() 函数可以使用多种格式化动词对输出进行格式化.下面是可以与所有数据类型一起使用的一些通用格式化动词: 以下动词适用于所有数据类型: 动词 描述 %v 以默认格式打印值 %#v 以 Go ...

  10. Health Kit接入资质要求详解,开发不迷路!

    开发运动/健康应用过程中,需要使用Health Kit提供的数据能力,作为独立的个人开发者或是企业开发者,接入时分别需要满足什么样的条件呢? 个人开发者接入资质审核要求 •个人开发者应用需上架至华为应 ...