C#输出参数

问题描述:

以下两个代码片段有什么区别?C#输出参数

public void foo(out classA x) 
{ 
    y = new classA(); 
    x = y; 
} 

与第二:

public void foo(out classA x) 
{ 
    classA y; 
    x = y; 
} 

这是真的,第二个片段是危险的,因为x现在有一个参考这个地方y,退出foo后,这可能是已经死了吗?

为什么我们一般使用“新”?

我有点困惑,因为在C++中,如果x在第二个片段将是一个指针,语句x = y甚至不会因为y编译不是指针。

+11

它们都没有编译。 –

+1

第二个是不危险的。这是没用的,因为你永远不会为y赋值。 – JohnFx

+1

在C#中,类总是分配在堆上,所以你不必担心。 – Gabe

你的混乱,我想是,在C++第二示例将返回一个参照本发明的堆栈分配的对象。这在C#中不会发生。

鉴于C#你的第二个例子:

public void foo(out classA x) 
{ 
    classA y; // Doesn't allocate an object 
    x = y; 
} 

这可能不会编译,无论如何,因为y从未赋值。

让我们假设一下,如果第二个片段是

public void foo(out classA x) 
{ 
    classA y = new classA(); 
    x = y; 
} 

的片断,你写它不C#编译的。必须先分配y。行classA y;不会像在C++中那样在堆栈上创建classA的实例。它只是声明classA类型的变量y

考虑到的编译代码段,分配一个out变量本地声明和初始化对象是不以任何方式危险。该classA对象y点,并分配给x仍然活得很好,直到x超出无论它的声明/使用范围。

+1

我想补充一点,.NET使用引用计数来跟踪所创建的实例,所以不像C++,你在本地创建实例会当它超出范围去分配的'实例上面确实y'没有超出范围,而是在函数退出时将一个引用添加到“正在使用”计数(x)中,然后减去一个引用(y)。当其“正在使用”计数下降到0时,垃圾收集器就会出现并实际从内存中移除它。在哪一刻它已经消失了。 – CodingGorilla

+2

@CodingGorilla .NET CLR不使用引用计数。垃圾收集器遍历对象树并跟踪运行代码不再可访问的引用。 –

+1

你是对的,我试图解释这个观点,即只要它在使用中,这个实例就一直存在于内存中,并且这是一个不好的方法来解释它(特别是因为引用计数是一种完全不同的技术),但希望我们两个人之间他得到了这个想法。 – CodingGorilla

这是真的,第二个片段是危险[...]

不是在C#;你正在考虑像C或C++这样的本地语言,它允许我们将一个指针指向一个局部变量。在C#中,所有内容(在合理范围内)都是对托管对象的引用。一切都基本上在堆上。

这是不危险的,因为代码将无法被编译,除非所有的“出”参数给出的方法返回或退出之前的定义。