【.Net底层剖析】2.stfld指令-给对象的字段赋值

简介: 【.Net底层剖析】2.stfld指令-给对象的字段赋值

·

阅读目录

.Net底层剖析目录章节

1.【深入浅出.Net IL】1.一个For循环引发的IL

2.【.Net底层剖析】2.stfld指令-给对象的字段赋值

3.【.Net底层剖析】3.用IL来理解属性

 

引言:

  这篇我们讲解在.net  IL中间语言中,经常见到的指令stfld

  该指令经常用在给一个对象的字段赋值。

一、指令用途:

  MSDN解释如下:

  Replaces the value stored in the field of an object reference or pointer with a new value.

  翻译过来就是:用一个新值替换对象字段的值

二、命名空间和程序集

  命名空间是在  System.Reflection.Emit这个里面

  程序集是mscorlib(mscorlib.dll)

三、指令执行机制

  工作原理即堆栈转换行为如下:

  按照先后顺序:

    1.将一个对象引用或指针压入堆栈

    2.将值被压入堆栈

    3.该值和对象的引用/指针从堆栈中弹出,对象的字段更新为替换的值

四、 实例代码分析:

C#程序:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Test test1=new Test();//new一个Test对象
            test1.i = 12;//将Test对象的字段i赋值为12
        }
        /// <summary>
        /// 测试类
        /// </summary>
        public class Test
        {
            public int i = 100;
        }
    }
}

 

IL 程序Main方法

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       16 (0x10)
  .maxstack  2
  .locals init ([0] class ConsoleApplication1.Program/Test test1)
  IL_0000:  nop
  IL_0001:  newobj     instance void ConsoleApplication1.Program/Test::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldc.i4.s   12
  IL_000a:  stfld      int32 ConsoleApplication1.Program/Test::i
  IL_000f:  ret
} // end of method Program::Main

我们来逐行分析下main方法的IL代码

.entrypoint  //定义函数的入口点

 // Code size       16 (0x10)//代码大小为16

 .maxstack 2//栈的大小为2

 .locals init ([0] class ConsoleApplication1.Program/Test test1)//定义一个变量为test1,存储在<本地变量列表>中第一个变量中

 IL_0000:  nop//空操作

IL_0001:  newobj     instance void ConsoleApplication1.Program/Test::.ctor()//new 一个Test对象,一个引用指向这个对象,引用存放在栈上,

对象存放在堆上面

IL_0006:  stloc.0//将引用弹栈,存放到<本地变量列表>中的第一个变量中

 IL_0007:  ldloc.0//<本地变量列表>中第一个变量的值压入堆栈

 IL_0008:  ldc.i4.s   12//int 12压入堆栈

IL_000a:  stfld      int32 ConsoleApplication1.Program/Test::i//将堆栈的栈顶的值赋值给堆栈的第二个值,即test.i=12

 IL_000f:  ret//函数返回

五、内存分析

在指令stfld 执行之前的内存图

图片.png

 

堆栈中存放12test1的地址,<本地变量列表>第一个变量中存放的是test1的地址,堆中存放的是test1指向的一个对象,其中test1.i=100

 

在指令stfld 执行之后的内存图

图片.png

 

 

 

堆栈中的12test1的地址弹出,<本地变量列表>第一个变量中存放的是test1的地址不变,堆中存放的是test1.i=12

 

六、总结

本篇主要讲的就是对象的字段如何在内存中是如何赋值的,以及从每一行IL指令分析stfld 的执行过程。从底层分析对象的字段的赋值,可以更加清晰地看到赋值的过程。

 

下篇我会从.net底层剖析参数的传递,有兴趣的可以关注我哦!

 




相关文章
|
容器
.NET Core-作用域与对象释放行为详解
.NET Core-作用域与对象释放行为详解
|
3月前
|
存储 开发框架 .NET
ASP.NET Web Api 使用 EF 6,DateTime 字段如何取数据库服务器当前时间
ASP.NET Web Api 使用 EF 6,DateTime 字段如何取数据库服务器当前时间
|
3月前
|
程序员 数据库
分享 2 个 .NET EF 6 只更新某些字段的方法
分享 2 个 .NET EF 6 只更新某些字段的方法
|
5月前
|
开发框架 .NET API
ASP.NET Core Web中使用AutoMapper进行对象映射
ASP.NET Core Web中使用AutoMapper进行对象映射
|
5月前
|
编译器 C# C++
【.NET Core】C#预处理器指令
【.NET Core】C#预处理器指令
58 1
|
6月前
|
C#
.NET开发中合理使用对象映射库,简化和提高工作效率
.NET开发中合理使用对象映射库,简化和提高工作效率
191 0
|
JSON 数据格式
.NET Core - 配置绑定:使用强类型对象承载配置数据
.NET Core - 配置绑定:使用强类型对象承载配置数据
|
容器
.NET Core作用域与对象释放行为详解
上节,我们提到,容器中有3种不同生命周期,分别是Singleton、Scoped和Transient。那么,你知道这3种类型的对象的释放时机和坑吗?
|
SQL 存储 缓存
SQl Server——ADO.NET五大对象
在某些编程中总是会需要用到数据库,那如何让应用程序和数据库之间建立联系呢?ADO.NET就提供了应用程序连接数据库的桥梁
|
机器学习/深度学习 人工智能 计算机视觉
YOLOv7 在 ML.NET 中使用 ONNX 检测对象
本文介绍如何在 ML.NET 中使用 YOLOv7 的 ONNX 模型来检测图像中的对象。
435 0
YOLOv7 在 ML.NET 中使用 ONNX 检测对象