- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
当执行行超出代码块时,变量会发生什么变化?例如:
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/
为什么禁用类型像 type t = A of int | B of string * mutable int 虽然允许此类类型: type t = A of int | B of string * i
我正在寻找一种类似结构的数据结构,我可以从中创建多个实例并具有某种类型提示而不是不可变的。 所以我有这样的东西: class ConnectionConfig(NamedTuple): nam
我需要转到引用的结构: class SearchKnot { var isWord : Bool = false var text : String = "" var to
如sec 10.4.3中所述 当控制进入执行时,执行以下步骤 功能对象F(调用者)中包含的功能代码的上下文 提供thisArg,而调用方提供argumentsList: 如
i make a game that start display Activity indicator And activity indicator bottom display UiLable wi
编辑:我在这里不断获得支持。只是为了记录,我认为这不再重要。自从我发布它以来我就不再需要它了。 我想在 Scala 中执行以下操作... def save(srcPath: String, destP
使用可变对象作为 Hashmap 键是一种不好的做法吗?当您尝试使用已修改足以更改其哈希码的键从 HashMap 中检索值时,会发生什么? 例如,给定 class Key { int a; /
如果您在Kotlin中访问List类型的Java值,则将获得(Mutable)List!类型。 例如。: Java代码: public class Example { public stati
我编写了 str 类(内置)的以下扩展,以便执行以下操作:假设我有字符串 "Ciao" ,通过做"Ciao" - "a"我想要的结果是字符串 "Cio" 。这是执行此操作的代码,并且运行良好: cla
使用可变对象作为 Hashmap 键是一种不好的做法吗?当您尝试使用已修改足以更改其哈希码的键从 HashMap 中检索值时,会发生什么? 例如,给定 class Key { int a; /
我正在为我的公司设计一个数据库来管理商业贷款。每笔贷款都可以有担保人,可以是个人或公司,在借款业务失败时作为财务支持。 我有 3 个表:Loan、Person 和 Company,它们存储明显的信息。
我使用二进制序列化从 C# 类中保存 F# 记录。一切正常: F#: type GameState = { LevelStatus : LevelStatus
import javax.swing.JOptionPane; public class HW { public static void main(String[] args) { Strin
使用 flatbuffer mutable 有多少性能损失? 是否“正确”使用 FlatBuffers 来拥有一个应该可编辑的对象/结构(即游戏状态) 在我的示例中,我现在有以下类: class Ga
std::function create_function (args...) { int x = initial_value (args...); return [x] () mut
我需要在 for 循环中找到用户输入的字符。我通常会这样做 如果(句子[i] == 'e') 但是因为在这里,'e' 将是一个单字母字符变量,我不知道如何获取要比较的值。我不能只输入 if (sent
我有一个这样的算法: let seed: Foo = ... let mut stack: Vec = Vec::new(); stack.push(&seed); while let Some(ne
这个问题可能看起来非常基础,但我很难弄清楚如何做。我有一个整数,我需要使用 for 循环来循环整数次。 首先,我尝试了—— fn main() { let number = 10; // An
如果我有以下结构: struct MyStruct { tuple: (i32, i32) }; 以及以下函数: // This will not compile fn function(&mut s
我希望在每个 session 的基础上指定列的默认值。下面的脚本不起作用,但描述了我想如何使用它。我目前使用的是 MySQL 5.5.28,但如果需要可以升级。 CREATE TABLE my_tbl
我是一名优秀的程序员,十分优秀!