我想知道创建新对象作为方法(或构造函数调用)的一部分是否安全
如下面的拙劣例子:
public class Igloo
{
public int i = 5;
}
public class Program
{
static void Main(string[] args)
{
DoSomething(new Igloo());
}
private static void DoSomething(Igloo i)
{
Debug.WriteLine(i.i);
}
}
创建像这样的临时对象不赞成? 是否正确清理了创建的新对象。
答案 0 :(得分:6)
这没有错。
在发布模式下,为对象创建变量应该最终编译为相同的IL(免责声明:我没有检查过)。
答案 1 :(得分:3)
SLaks是对的 - 这是完全正常的,并且与所有意图和目的完全相同:
Igloo igloo = new Igloo();
DoSomething(igloo);
在Igloo
实例传递给DoSomething
方法后的两种情况下 - 此时无法再从Main
方法中访问实例,使实例可以读取DoSomething
方法完成后收集。
如果我们想了解更详细的内容,请查看IL:
.method private hidebysig static
void Main (string[] args) cil managed
{
// Method begins at RVA 0x2060
// Code size 13 (0xd)
.maxstack 8
.entrypoint
IL_0000: nop
IL_0001: newobj instance void ConsoleApplication1.Igloo::.ctor()
IL_0006: call void ConsoleApplication1.Program::DoSomething(class ConsoleApplication1.Igloo)
IL_000b: nop
IL_000c: ret
}
解释这意味着什么;我们在IL_0001
上看到我们创建了Igloo
的新实例 - 由于CLR是基于堆栈的虚拟机,因此该指令将对该实例的引用推送到堆栈。下一条指令是对DoSomething
的调用 - 再次CLR是一个基于堆栈的虚拟机,因此参数从左到右被压入堆栈(因此堆栈中的最后一项是最右边的参数) 。在这种情况下,由于上一次操作,只有一个参数并且它已经在堆栈中,因此我们准备调用我们的方法。
如果我们将这与我们进行以下修改时产生的IL进行比较:
Igloo igloo = new Igloo();
DoSomething(igloo);
我们只能看到几个重要的差异:
.method private hidebysig static
void Main (string[] args) cil managed
{
// Method begins at RVA 0x2060
// Code size 15 (0xf)
.maxstack 1
.entrypoint
.locals init (
[0] class ConsoleApplication1.Igloo igloo
)
IL_0000: nop
IL_0001: newobj instance void ConsoleApplication1.Igloo::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: call void ConsoleApplication1.Program::DoSomething(class ConsoleApplication1.Igloo)
IL_000d: nop
IL_000e: ret
}
除了声明本地化的方法的开头,唯一的区别是创建stloc.0
和我们对ldloc.0
的调用之间的Igloo
和DoSomething
调用。这是什么?
stloc.0
是一个从堆栈中弹出最后一项并将其存储在第0个本地的指令。注意,此时我们不再有正确的堆栈来调用DoSomething
(我们需要我们的Igloo
实例位于堆栈的顶部)这是ldloc.0
的用途 - 它推动第0个本地(后面)到堆栈。基本上这两个指令是我们的任务。
请注意,当JITer将其编译为机器代码时,这两个语句几乎肯定会被优化掉。
答案 2 :(得分:2)
如果您创建一个Windows窗体项目而不是一个控制台项目,您将在program.cs中找到以下行:
Application.Run(new FormMain());
因此,MS似乎也与Windows窗体项目的默认值完全相同。
答案 3 :(得分:1)
这在c#中是安全和标准的,所有垃圾收集器一旦无法访问就会收集这些对象。
答案 4 :(得分:1)
是的,是的。该对象将在以后自动删除。