gpt4 book ai didi

c# - 可变生命周期

转载 作者:太空狗 更新时间:2023-10-30 00:24:00 32 4
gpt4 key购买 nike

当执行行超出代码块时,变量会发生什么变化?例如:

1  public void myMethod()
2 {
3 int number;
4 number = 5;
5 }

因此,我们声明并设置变量。当它超出代码块(第 5 行)时,变量号会发生什么变化?

这是另一个创建类实例的例子:

7   public void myMethod()
8 {
9 Customer myClient;
10 myClient = new Customer();
11 }

当它超出代码块(第 11 行)时,对象引用 myClient 会发生什么?

我想在这两种情况下变量都被分配了,但是什么时候被释放了?

最佳答案

作为变量,它是C# 语言中的一个概念。在代码块之外没有任何“发生”,因为它在代码块内。这句话之外的单词 word 没有任何变化。

当然,您的意思是代码运行时变量会发生什么变化,但值得记住这种区别,因为在考虑这个问题时,我们正在转向变量与 C# 中不同的级别。

在这两种情况下,代码都被转换为 CIL,然后在运行时转换为机器码。

CIL 可能会有很大差异。例如,下面是第一个在 Debug模式下编译时的样子:

.method public hidebysig instance void myMethod () cil managed 
{
.locals init ([0] int32) // Set-up space for a 32-bit value to be stored
nop // Do nothing
ldc.i4.5 // Push the number 5 onto the stack
stloc.0 // Store the number 5 in the first slot of locals
ret // Return
}

下面是编译发布时的样子:

.method public hidebysig instance void myMethod () cil managed 
{
ret // Return
}

由于未使用该值,编译器将其作为无用的垃圾删除并仅编译一个立即返回的方法。

如果编译器没有删除这样的代码,我们可能会想到:

.method public hidebysig instance void myMethod () cil managed 
{
ldc.i4.5 // Push the number 5 onto the stack
pop // Remove value from stack
ret // Return
}

调试构建存储东西的时间更长,因为检查它们对调试很有用。

当发布版本确实将内容存储在本地数组中时,它们也更有可能在方法中重用槽。

然后将其转换为机器代码。它的工作方式类似,它要么产生数字 5,将其存储在本地(在堆栈或寄存器中),然后再次删除它,要么什么都不做,因为未使用的变量已被删除. (也许甚至不执行该方法;可以内联该方法,然后由于它不执行任何操作而被有效地完全删除)。

对于带有构造函数的类型,还有更多的事情要做:

.method public hidebysig instance void myMethod () cil managed 
{
.locals init ([0] class Temp.Program/Customer) // Set-up space for a reference to a Customer

nop // Do nothing.
newobj instance void SomeNamespace/Customer::.ctor() // Call Customer constructor (results in Customer on the stack)
stloc.0 // Store the customer in the frist slot in locals
ret // Return
}

.method public hidebysig instance void myMethod () cil managed
{
newobj instance void SomeNamespace/Customer::.ctor() // Call Customer constructor (results in Customer on the stack)
pop // Remove value from stack
ret // Return
}

这里都调用构造函数,甚至发布版本也会调用构造函数,因为它必须确保任何副作用仍然发生。

如果 Customer 是引用类型,还会发生更多情况。如果它是一个值类型,那么它的所有内容都保存在堆栈中(尽管它可能具有依次为引用类型的字段)。如果它是引用类型,那么堆栈中保存的是对堆中对象的引用。当堆栈上不再有任何此类引用时,垃圾收集器将不会在其扫描中找到它以查找它无法收集的对象,并且可以收集它。

在发布版本中,一旦构造函数返回,可能永远不会有存储该引用的内存位置或寄存器。实际上,即使构造函数正在运行(如果没有字段访问或对 this 的其他隐式或显式使用发生),也可能没有一个,或者它可能已经被部分删除(一旦这样的访问已经完成),因此垃圾收集甚至可能在构造函数完成之前发生。

更有可能在方法返回后它会在堆内存中停留一段时间,因为 GC 尚未运行。

关于c# - 可变生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31137225/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com