dotnet C# 多次对一个对象调用构造函数会发生什么
今天来玩一点变态的,使用反射获取到某个类型的构造函数,接着多次对此类型的某个对象调用构造函数方法。请问此时会发生什么
假定有一个类型 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 属性的任何值。也因为构造函数只是一个函数,因此调用多次就和调用一个方法多次是一样的
可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 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# 多次对一个对象调用构造函数会发生什么的更多相关文章
- [C++基础]在构造函数内部调用构造函数
看下面的面试题: #include <iostream> using namespace std; struct CLS { int m_i; CLS( int i ) : m_i(i){ ...
- 为什么字符串类型可以调用构造函数String的方法,却又不是它的实例
从所周知,在js中定义一个字符串我们有两种办法: var a = new String("a"); var a = "a"; 第一种方法使用构造函数创建,作为S ...
- 转:C++何时调用构造函数,何时调用析构函数
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/wjf1997/article/detai ...
- java静态方法调用&&构造函数&&静态块
静态方法,也就是使用static声明的方法,在虚拟机启动加载类的时候就进行了创建,所以使用到静态方法时,直接使用类名点静态方法即可调用.java在执行静态方法前,不会调用构造函数:构造函数是在实例化j ...
- c++ 对象复制引用时何时调用构造函数、析构函数
class TEST{ private : public : TEST() {std::cout << "constructor" << std::endl ...
- c++构造函数中调用构造函数---匿名对象再探
#include<iostream> #include<string> using namespace std; class Copy_construction { publi ...
- javaScript 调用构造函数 Array() 时没有使用参数, length总是0
如果调用构造函数 Array() 时没有使用参数,那么返回的数组为空,length 字段为 0. 当调用构造函数时只传递给它一个数字参数,该构造函数将返回具有指定个数.元素为 undefined 的数 ...
- Java构造函数中调用构造函数
在Java中,当为一个类创建了多个构造函数时,有时想在一个构造函数中调用另一个构造函数以减少代码量.这时可以使用this关键字来实现. 通常,当使用this关键字时,它意味着"这个对象&qu ...
- 牛客网Java刷题知识点之构造函数可以调用一般函数,但是一般函数不可以直接调用构造函数
不多说,直接上干货! 通过 牛客网Java刷题知识点之构造函数是什么.一般函数和构造函数什么区别呢.构造函数的重载.构造函数的内存图解 我们对构造函数有了一个比较清楚的认识,当我们在创建对象时,我们会 ...
- C# this调用构造函数及析构函数
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace trai ...
随机推荐
- 【Leetcode】768. 最多能完成排序的块 II
题目(链接) arr是一个可能包含重复元素的整数数组,我们将这个数组分割成几个"块",并将这些块分别进行排序.之后再连接起来,使得连接的结果和按升序排序后的原数组相同. 我们最多能 ...
- JavaScript知识总结 基础篇
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 1. new操作符的实现原理 new操作符的执行过程: (1)首先创建了一个新的空对象 (2)设置原型,将对象的原型设置为函数的 prot ...
- Rust使用Sauron实现Web界面交互
目录 简介 架构 Application 和组件 简单入门示例 先决条件 创建新项目 编译库文件 引用库文件 运行项目 界面交互示例 创建项目 编译库文件 引用库文件 引用库文件 运行项目 参考资料 ...
- AXI4协议的物理模型
AXI4的物理传输模型 1.AXI4的组成部分 首先说一下文章是学习<基于AXI4的IP核互联的设计与验证>莫锦辉的学习笔记.文中大部分的知识都是来源于这篇论文,这里学习以便理解AXI4协 ...
- KinbaseES 优化之IO优化
IO 资源作为目前服务器中最昂贵的资源之一,是目前绝大部分业务系统主要的瓶颈资源,原因就在于服务器相关的硬件资源中IO资源的性能提升是难度最大的.存储的发展步伐远低于内存和CPU的发展. 在数据库管理 ...
- 程序员/后端开发方向Java 跳槽注意事项(简历和面试经验分享)
程序员/后端开发方向Java 跳槽注意事项(简历和面试经验分享) 应届生面试经验参考:https://www.cnblogs.com/rainbow-1/p/16779048.html 简历: 1.个 ...
- AndroidStudio开发体温上报安卓APP------问题总结
总结一下出现的问题: 1.首先是AndroidStudio的配置问题 在这里可以看sdk版本配置 这里可以看gradle的版本信息和下载目录 AndroidStudio手动配置gradle 1.首先编 ...
- C++ Break、Continue 和 数组操作详解
C++ Break 和 Continue break 语句还可以用来跳出循环. 在以下示例中,当 i 等于 4 时跳出循环: for (int i = 0; i < 10; i++) { if ...
- Pandas统计计算
基本的统计方法 Method Description count Number of non-NA values describe Compute set of summary statistics ...
- CentOS 6.5 ZIP、RAR文件压缩解压操作详解
============zip文件的操作================= zip -r data.zip data 解释:将data文件夹压缩成了data.zip格式. unzip data.z ...