I am a beginner in C#, I don't know why this isn't working, I just want to set this object to null by calling Dispose()
method.
Why this is not possible?
class MyClass:IDisposable
{
public void Dispose()
{
this = null;
}
}
I am a beginner in C#, I don't know why this isn't working, I just want to set this object to null by calling Dispose()
method.
Why this is not possible?
class MyClass:IDisposable
{
public void Dispose()
{
this = null;
}
}
该Dispose
方法的目的不是清理该类,而是清理该类所持有的一次性依赖项,以便垃圾收集器可以正常处理它。
我建议阅读更多关于该Dispose
模式以及如何在 C# 中实现它的信息。
有点迂腐:该Dispose
方法不是析构函数,也不是终结器。
您的问题似乎真的可以归结为“如何删除 C# 中的内容”。简短的回答是你不能,这是垃圾收集器的工作System.GC
。IDisposable
接口用于确保按需清理不属于 .Net的重要资源(如文件或网络/数据库连接,但不属于 .Net 类)。
界面很重要,IDisposable
因为它允许您使用该using
模式。也就是说,如果你的类实现IDisposable
了它可以在一个using
块中使用。例如考虑:
class MyClass : IDisposable {
public void Dispose() { }
}
这个类现在可以像这样使用:
using (MyClass instance = new MyClass())
{
} // instance.Dispose() is called here at the end of the block.
using 块的要点是,当块结束时,编译器将抛出一个调用Dispose()
,您可以使用该调用来摆脱文件和数据库连接等重要资源。例如,所有的Stream
类,喜欢FileStream
什么不实现IDisposable
,因为让文件保持打开状态是个坏主意。相反,您将所有访问权限包装在一个using
块中,然后保证FileStream.Dispose
将关闭文件。考虑:
using (FileStream myFile = File.OpenRead("..."))
{
// Read the content of the file.
} // The file is guaranteed to be closed here. Cool!
这比做这样的事情要整洁得多:
FileStream stream = File.OpenRead(" ... ");
stream.Close(); // Yes, you closed it manually, but it's error prone. What if you forget to do this?
现在您想到的是一个称为“最终化”的术语,即该类实际上被销毁的时候。当垃圾收集器(System.GC
类)实际销毁对象并清理它们的内存时,就会发生这种情况。考虑:
public class MyClass {
// This method, the 'Finalizer' will be called when the class is destroyed.
// The 'finalizer' is essentially just the name of the class with a '~' in front.
~MyClass() {
Console.WriteLine("Destroyed!");
}
}
public class Program {
public static void Main() {
MyClass referenceHeld = new MyClass(); // Reference held
new MyClass(); // No reference held on this class
WeakReference sameAsNoReference = new WeakReference(new MyClass()); // Equivalent to no reference.
System.GC.Collect(); // Force the garbage collector to collect
Console.ReadLine();
}
}
简而言之,垃圾收集器是运行时的一部分,用于清理未使用的东西。不被使用是什么意思?这意味着没有附加到对象的引用。例如,如果你运行上面的程序,你会注意到“Destroyed”这个词在屏幕上打印了两次。这是因为函数中MyClass
created的两个实例Main
没有被引用指向(AWeakReference
本质上与无引用相同)。当我们调用GC.Collect()
垃圾收集器时,它会运行并清理引用。
也就是说,你不应该自己GC.Collect
打电话。当然,您可以进行实验和教育,但大多数人会告诉您,垃圾收集器在自己保持清洁方面做得很好。在你的代码中散落一堆是没有意义的GC.Collect
,因为这就是拥有垃圾收集器的全部意义——不必担心自己清理东西。
所以简而言之,你真的不能自己销毁对象,除非你打电话GC.Collect()
(你不应该这样做)。该IDisposable
接口允许您使用该using
模式,确保释放重要资源(但这与销毁对象不同!IDisposable
所做的只是确保Dispose()
在块退出时调用它,using
以便您可以清理重要的东西,但是对象还活着 - 一个重要的区别)。
一个类不能使自己为空,因为它无法控制谁在引用它。例如,如果您的代码中有一个带有对象的变量,则该对象不能在您的代码中使自己为空,它只能将其 OWN 成员设置为空。
除此之外,想想多个类引用同一个对象的情况,他会在哪里为空?这是包含类应该做的事情。
简单的答案是“this”关键字是只读的,不能设置。
一个更长更基本的答案是您不能在 c# 中将对象本身设置为 null,但是您可以将对对象的引用设置为 null。当您将对象的引用设置为 null 并且没有其他对象引用该对象时,即该对象处于垃圾收集状态。(这是对实际发生的事情的简化。)
例如:
Object oTest = new Object;
oTest = null;
在上面的示例中,对象在其引用 oTest 设置为 null 后仍然存在。它只是在等待垃圾收集器出现并删除它。
因此,在您的代码中,您似乎试图将所有对对象的引用设置为 null,即使这可能不是您想要的。这不能从对象本身完成。您需要确保对您的对象的所有引用都手动设置为 null 或者保证它们在您的程序中保留范围。
仅当您使用非 CLR 资源时才需要 Dispose 模式,例如图形上下文或低级 io。当你现在需要释放资源时会有一些极端情况,但正如你所说的你是一个初学者,你真的不应该打扰(还)。
设置this
为零没有帮助。考虑这个
MyClass sample = new MyClass();
sample.Dispose();
// at this point, sample still has a value
当你想在 C# 中删除一个对象时,你只需要让所有的引用都超出范围,或者将它们设置为 nil。(多个变量可以引用同一个实例)。运行时将自动释放对象(及其子对象),因为没有人再使用它了。
粗略地说,您可以将它们视为指针(技术上它们不是,但我们在这里试图解释原理)
你不能修改你的this
指针。在您的示例中,您的 Dispose 方法不需要执行任何操作,因此可以完全省略(以及更新类以不再实现IDisposable
)