如何在 C# 中处理托管和非托管对象?
How to dispose managed and unmanaged objects in C#?
全部。我从来没有使用过析构函数也没有处理过,所以这对我来说是新的。
我的任务是做一个 class,它有析构函数和处置方法,它有一个自动增量的 UInt64
Id 属性,和一个必须的静态 Dictionary<UInt64,MyClass>
通过 Id 引用 live MyClass
.
实例
在搜索了如何正确使用它们之后,这就是我最终做的事情:
public class MyClass : IDisposable
{
private static Object Lock = new Object();
private static Dictionary<UInt64, MyClass> LiveInstances = new Dictionary<UInt64, MyClass>();
public UInt64 Id { get; private set; }
public MyClass()
{
lock (Lock)
{
var newId = IncrementalId();
if (newId == 0)
{
throw new ArgumentException("Reached MAX VAL");
}
Id = newId;
LiveInstances.Add(Id, this);
}
}
~MyClass()
{
CleanUpNativeResources();
}
public void Dispose()
{
lock (Lock)
{
CleanUpManagedResources();
CleanUpNativeResources();
GC.SuppressFinalize(this);
}
}
protected virtual void CleanUpManagedResources()
{
LiveInstances.Remove(Id);
}
protected virtual void CleanUpNativeResources()
{
}
private static UInt64 IncrementalId()
{
for (ulong i = 0; i <= Convert.ToUInt64(LiveInstances.Count) ; i++)
{
if (i != UInt64.MaxValue && !LiveInstances.ContainsKey(i + 1))
{
return i+1;
}
}
return 0;
}
}
现在,我的问题是 如何处理对象? 无论我是否尝试查找处理对象的示例,我都会找到类似这个:
// Code to dispose the managed resources of the class
Console.WriteLine("Object disposed");
提前致谢。
托管资源将在某个时间点由垃圾收集器自动处理。非托管资源类似于文件句柄,通过 Windows API 调用 returns 必须手动释放的 Windows 句柄获得。您没有任何需要手动处理的东西。
如果您不释放这些句柄,它们将在程序运行期间保持分配状态,但所有具有非托管资源的 .Net classes 都提供 Finalizer
(见下文)以确保他们通常会在某个时候被释放。
(但如果您正在编写自己的文件处理程序 class 并且忘记在任何地方释放文件句柄,文件将保持打开状态直到您的程序退出。)
通常这种非托管资源会在两个地方被释放:
Dispose()
方法。这应该是您处理非托管资源的正常方式。
终结器。这是最后的手段机制。如果 class 有终结器,垃圾收集器在清理死对象时会调用它。如果程序员忘记调用 Dispose(),任何具有非托管资源的 class 都应该有一个终结器来清理。
使用的基本 Dispose 模式是这样的:
class MyObject : IDisposable
{
//indicates if dispose has already been called
//private bool _disposed = false;
//Finalize method for the object, will call Dispose for us
//to clean up the resources if the user has not called it
~MyObject()
{
//Indicate that the GC called Dispose, not the user
Dispose(false);
}
//This is the public method, it will HOPEFULLY but
//not always be called by users of the class
public void Dispose()
{
//indicate this was NOT called by the Garbage collector
Dispose(true);
//Now we have disposed of all our resources, the GC does not
//need to do anything, stop the finalizer being called
GC.SupressFinalize(this);
}
private void Dispose(bool disposing)
{
//Check to see if we have already disposed the object
//this is necessary because we should be able to call
//Dispose multiple times without throwing an error
if (!disposed)
{
if (disposing)
{
//clean up managed resources
components.Dispose();
}
//clear up any unmanaged resources - this is safe to
//put outside the disposing check because if the user
//called dispose we want to also clean up unmanaged
//resources, if the GC called Dispose then we only
//want to clean up managed resources
}
}
}
全部。我从来没有使用过析构函数也没有处理过,所以这对我来说是新的。
我的任务是做一个 class,它有析构函数和处置方法,它有一个自动增量的 UInt64
Id 属性,和一个必须的静态 Dictionary<UInt64,MyClass>
通过 Id 引用 live MyClass
.
在搜索了如何正确使用它们之后,这就是我最终做的事情:
public class MyClass : IDisposable
{
private static Object Lock = new Object();
private static Dictionary<UInt64, MyClass> LiveInstances = new Dictionary<UInt64, MyClass>();
public UInt64 Id { get; private set; }
public MyClass()
{
lock (Lock)
{
var newId = IncrementalId();
if (newId == 0)
{
throw new ArgumentException("Reached MAX VAL");
}
Id = newId;
LiveInstances.Add(Id, this);
}
}
~MyClass()
{
CleanUpNativeResources();
}
public void Dispose()
{
lock (Lock)
{
CleanUpManagedResources();
CleanUpNativeResources();
GC.SuppressFinalize(this);
}
}
protected virtual void CleanUpManagedResources()
{
LiveInstances.Remove(Id);
}
protected virtual void CleanUpNativeResources()
{
}
private static UInt64 IncrementalId()
{
for (ulong i = 0; i <= Convert.ToUInt64(LiveInstances.Count) ; i++)
{
if (i != UInt64.MaxValue && !LiveInstances.ContainsKey(i + 1))
{
return i+1;
}
}
return 0;
}
}
现在,我的问题是 如何处理对象? 无论我是否尝试查找处理对象的示例,我都会找到类似这个:
// Code to dispose the managed resources of the class
Console.WriteLine("Object disposed");
提前致谢。
托管资源将在某个时间点由垃圾收集器自动处理。非托管资源类似于文件句柄,通过 Windows API 调用 returns 必须手动释放的 Windows 句柄获得。您没有任何需要手动处理的东西。
如果您不释放这些句柄,它们将在程序运行期间保持分配状态,但所有具有非托管资源的 .Net classes 都提供 Finalizer
(见下文)以确保他们通常会在某个时候被释放。
(但如果您正在编写自己的文件处理程序 class 并且忘记在任何地方释放文件句柄,文件将保持打开状态直到您的程序退出。)
通常这种非托管资源会在两个地方被释放:
Dispose()
方法。这应该是您处理非托管资源的正常方式。
终结器。这是最后的手段机制。如果 class 有终结器,垃圾收集器在清理死对象时会调用它。如果程序员忘记调用 Dispose(),任何具有非托管资源的 class 都应该有一个终结器来清理。
使用的基本 Dispose 模式是这样的:
class MyObject : IDisposable
{
//indicates if dispose has already been called
//private bool _disposed = false;
//Finalize method for the object, will call Dispose for us
//to clean up the resources if the user has not called it
~MyObject()
{
//Indicate that the GC called Dispose, not the user
Dispose(false);
}
//This is the public method, it will HOPEFULLY but
//not always be called by users of the class
public void Dispose()
{
//indicate this was NOT called by the Garbage collector
Dispose(true);
//Now we have disposed of all our resources, the GC does not
//need to do anything, stop the finalizer being called
GC.SupressFinalize(this);
}
private void Dispose(bool disposing)
{
//Check to see if we have already disposed the object
//this is necessary because we should be able to call
//Dispose multiple times without throwing an error
if (!disposed)
{
if (disposing)
{
//clean up managed resources
components.Dispose();
}
//clear up any unmanaged resources - this is safe to
//put outside the disposing check because if the user
//called dispose we want to also clean up unmanaged
//resources, if the GC called Dispose then we only
//want to clean up managed resources
}
}
}