三个问题:
在.NET / Java中应手动配置哪些变量?我知道SqlConnection应始终手动处理或在using {}块中使用。这样对吗?应该处理的其他变量是什么?
我在某地读过必须手动处理非托管代码。是对的吗?究竟什么是非托管代码?如何知道变量是托管还是非托管?
最后,我如何处理变量?我知道Dispose()方法并没有真正处理变量。那么Dispose()做什么呢?我应该将它们设置为null()吗?垃圾收集器的工作原理是什么?
答案 0 :(得分:5)
此答案仅涉及问题的.NET部分
在.NET / Java中应手动配置哪些变量?我知道 应该始终是SqlConnection 要么手动处理,要么用于 使用{}块。这样对吗?是什么 另一种变量 应该处理?
在.NET中,所有实现IDisposable
的对象都应该显式处理(或在using
块中使用)。
我在某地读过必须手动处理非托管代码。是 那对吗?究竟什么是不受管理的 代码以及如何知道变量 是管理还是不管理?
您可能意味着非托管资源,因为代码无法处理...所有使用非托管资源的类(不在托管堆上分配的内存,win32处理......)应该实现IDisposable
,并且应该因为它们不是由垃圾收集者管理的,所以要明确处理。
最后,我如何处置变量?我知道Dispose() 方法并没有真正处理掉 变量。那么Dispose()做什么呢? 我应该将它们设置为null()吗?什么是 垃圾的逻辑 收藏家的作品?
我不确定我理解你的问题......你没有处理变量,它是由垃圾收集器管理的。所有托管内存在不再使用时会自动释放(即代码无法访问它,因为没有任何引用)。 IDisposable.Dispose
方法仅适用于非GC管理的资源。
IDisposable
主要是用于清理非托管资源,但也经常用于执行其他清理操作和保证状态或数据完整性。例如,IDbTransaction
实现IDisposable
以便在事务提交之前发生异常时回滚事务:
using (var trx = connection.BeginTransaction())
{
// Do some work in the transaction
...
// Commit
trx.Commit();
} // the transaction is implicitly rolled back when Dispose is called
答案 1 :(得分:4)
在Java中,你“关闭”而不是“处置”。
某些第三方Java库或框架具有需要手动处理/关闭/销毁的类。
答案 2 :(得分:2)
.NET
实现IDisposable接口的所有对象都要求在不再需要时调用Dispose
方法。 using
块只是一个try-finally块的C#sugar,它将IDiposable
置于finally块中,只要它不为null即可。因此,即使在try块中抛出异常,也会发生处理。
Dispose
方法执行编写Dispose
方法的开发人员的任何代码!通常,这涉及释放不受运行时管理的“非托管”资源,例如数据库连接,窗口句柄和文件句柄。请注意,GC管理堆,因此在它引用的对象无法访问之前将引用设置为null并没有多大帮助。
这是good read。
答案 3 :(得分:1)
这主要由托马斯负责,但要扩展第三点:
最后,我如何处置变量?我知道Dispose() 方法并没有真正处理掉 变量。那么Dispose()做什么呢? 我应该将它们设置为null()吗?什么是 垃圾的逻辑 收藏家的作品?
他们的关键是Dispose()告诉对象释放它当前持有的任何非托管资源,它不会释放对象本身。
垃圾收集器知道如何释放对象,但对于IDisposable对象,只有对象本身知道如何处置它的私有资源,所以你必须确保在垃圾收集器释放对象之前调用Dispose()
答案 4 :(得分:1)
对于Java:
SWT是一个我们必须处理资源(如图像)的框架,因为框架使用必须释放的本机库和系统句柄。记录SWT课程,并在需要处理时告知。
答案 5 :(得分:1)
跟进其他.NET解决方案......
如果你的对象拥有非托管资源,那么在Dispose()调用上简单地清理它们是不够的,因为你不能保证会调用Dispose。完整的解决方案是:
答案 6 :(得分:1)
如果.net,如果你可以在“using”语句中使用一个对象,那意味着该对象实现了iDisposable,你应该在实际调用它时使用它的处理方法。请注意,处理方法可能并不总是称为“Dispose”,但您始终可以通过将对象强制转换为iDisposable然后在其上调用Dispose来调用它。
请注意,某些类型的“iDisposable”对象不处理任何非托管资源,但会订阅事件。如果没有正确处理这样的对象,它可能不会被垃圾收集,除非或直到它为其保存订阅事件的所有对象本身都是垃圾收集的。在某些情况下,这可能永远不会发生,直到应用程序退出。
例如,iEnumerable集合返回的枚举器可能会订阅该对象的“集合已更改”事件,并在调用其dispose方法时取消订阅。如果从未调用dispose方法,则只要集合执行,枚举器就会保持不变。如果集合本身保留了很长时间并且经常被枚举,这可能会造成巨大的内存泄漏。
答案 7 :(得分:1)
我同意上述内容,我只会添加有关将变量设置为null的后续问题。
您不需要对方法中使用的变量执行此操作(它们将超出范围,因此只有当它们在其中具有必须通过IDisposable.Disopse进行清理的状态时才会发出状态担心这个)。
它对于实例或静态成员很少有用,因为内存并不像人们通常认为的那样宝贵( 是一种宝贵的资源,但大多数人试图用几行来处理它)代码就像关闭你的水龙头一样,当你有一个爆裂的主力。
如果你有一个类的静态或实例成员并且(A)它是一个大对象(B),那么“拥有”对象可能会在内存中保留很长时间而且(C)你知道你不需要那个价值增益,把那个成员设置为空。
在实践中,这不是一个非常常见的组合。如果有疑问,请单独留下。
现在,请阅读其他答案,因为他们对Dispose()方法的评价更为重要。