具有函数作用域的变量
本文关键字:变量 作用域 函数 | 更新日期: 2023-09-27 17:50:03
CLR在抛出异常时如何处理具有函数作用域的局部变量。是否必须使用finally块,或者一旦流离开函数
,变量就被处置?下面是一个小例子
protected void FunctionX()
{
List<Employee> lstEmployees;
try
{
lstEmployees= new List<Employee>();
int s = lstEmployees[1].ID; // code intended to throw exception
}
catch (Exception ex)
{
ManageException(ex, ShowMessage); //exception is thrown here
}
finally { lstEmployees= null; } // Is the finally block required to make sure the list is cleaned
}
要回答您的具体问题,不,您列出的finally
块不是必需的。
将null
赋值给引用变量实际上并没有做任何事情,因为垃圾收集是不确定的。作为一个简单的解释,垃圾收集器将不时地检查堆中的对象,以确定是否有任何对它们的活动引用(这称为"扎根")。如果没有活动引用,则这些引用符合垃圾收集的条件。
您对null
的赋值是不需要的,因为一旦函数退出,lstEmployees
变量将脱离作用域,并且将不再被视为对您在try
块中创建的实例的活动引用。
有某些类型(在。net和第三方库中)实现IDisposable
接口并通过Dispose()
函数公开一些确定性清理过程。在使用这些类型时,应该在使用完类型后始终调用Dispose()
。如果实例的生存期不应该扩展到函数的生存期之外,那么您可以使用using() { }
块,但只有当类型实现了IDisposable
时才需要这样做,而List<T>
(如您在示例中使用的)不需要。
不要担心对象清理,这就是。net和大多数现代语言在运行时提供垃圾收集功能的原因。
如果你的对象有一个非托管资源的句柄,执行清理
其他一些答案在这里有点误导。
实际上,垃圾收集器与变量lstEmployees
(几乎)没有任何关系。但是它从不需要设置为null
,无论是在正常代码流中还是在抛出异常之后。
设置对null
的引用来释放它们所指向的对象几乎不需要,特别是对于局部对象。
因此,垃圾收集器也不会关心异常。
另一方面,不由CG 处理的非托管资源总是需要手动清理(通过IDisposable
接口的Dispose
方法)。为了确保在抛出异常后返回这些资源,您确实需要finally
子句。或者,如果您不打算在本地处理异常,您可以用using
子句替换try … finally
:
using (someUnmanagedResource) {
// … use the resource …
}
// Will implicitly call someUnmanagedResource.Dispose() *whatever happens*!
。. NET语言是垃圾收集的,这意味着对象的生命周期被跟踪,所以当垃圾收集发现没有更多的对象引用它时,它将摆脱你的列表。
一点也不。当变量超出作用域时,垃圾收集器将处理它(当GC决定是时候收集所有垃圾时…)
你唯一需要考虑的是,也许你不想等待GC完成它的工作,所以资源帮助一个类的实例被释放(例如,假设你在本地创建了一个实例,它拥有一个数据库连接的引用)。该连接将被保持,直到GC负责删除实例,然后删除引用的连接(这可能需要一段时间)。
在这些情况下,查看一下IDisposable接口,这样您就可以在实例被GC删除之前主动释放资源。
。. NET的垃圾收集器将为您处理此问题。实际上,将"lastEmployees"设置为null与退出函数的作用是一样的。
任何不再被根应用程序以一种或另一种形式引用的项将被标记为收集。
在。net中,您永远不需要担心清理托管资源。因此,管理。
http://msdn.microsoft.com/en-us/library/0xy59wtx.aspx