[英]C# is object valid
您可以檢查對象是否為null,但是可以檢查對象是否有效嗎?
Assert.IsValid(object_name);
例如,垃圾收集器已刪除該對象,或者某人已對其進行了處置。 但指針仍然指向該對象。
如果對象已被垃圾收集器釋放,則根據定義,您將不會引用該對象。
如果它被處理掉並且對於對象的有效性很重要,那么類型應該提供一種確定它的方法。 (例如,在某些情況下, Dispose
只是意味着“重置”。)
即使允許引用已處置對象的可能性,也很少適用 - 如果您使用:
using (Foo foo = new Foo())
{
...
}
然后該對象將在foo
超出范圍的同時被處理,因此這不是問題。
如果對象已被釋放,則沒有任何“實時”引用,因此您無法訪問它(保證沒有可讀取/寫入對象的可訪問代碼)(這在“安全”代碼中......在“不安全”代碼中沒有任何保證。但由於某種原因它是“不安全的”:-))
對於IDisposable
對象,“正確完成”類保留了一個標志,它們在每個方法/屬性中檢查( bool isDisposed = false
,在開頭,isDisposed = true;在Dispose()
),如果對象已經被處理,則它們會throw new ObjectDisposedException()
。
請注意,C#語言/ .NET運行時中沒有任何內容禁止“處置”對象被“重新點燃”,重新使用和“重新處理”,但是代碼編寫錯誤(並支持此“反模式“甚至還有一個GC.ReRegisterForFinalize
來平衡GC.SuppressFinalize
經常在Dispose()
完成
如果您有WeakReference
並且您想要檢查“僅用於統計目的”,如果仍然可以訪問該對象,則使用WeakReference.IsValid
。 如果要引用對象以使用它,可以使用WeakReference.Target
並檢查返回值是否為null
。 這個非常重要!!
var wr = new WeakReference(new List<int>());
// Right!!
var target = (List<int>)wr.Target;
if (target != null)
{
target.Clear();
}
// Wrong!! The GC could kick in after the if and before the target =
if (wr.IsAlive)
{
target = (List<int>)wr.Target;
target.Clear();
}
但是如果object_name首先沒有被收集,它將如何獲取垃圾?
如果指針仍指向對象(根據您的問題),那么對象將無法收集垃圾
將對象存儲在WeakReference列表中。
使用IsAlive
屬性檢查對象是否已被垃圾回收。
根據定義,垃圾收集器不會刪除“非垃圾”對象,包括代碼保存引用的對象。
由於IDisposable合同不包含這樣的方法,因此沒有通用的方法來查看對象是否已被處置。 但是許多類都有一種確定其狀態的方法,例如SqlConnection類有一個State屬性,它將在已處置的對象上返回ConnectionState.Closed。
在GC
和自定義對象狀態方面,您只能檢查對象是否已使用代數移動
int objectGeneration = GC.GetGeneration(objectInstance)
但你不能訪問GCed對象或檢查對象是否已被Disposed
因為Dispose()
是每個特定IDisposable
類型的自定義實現,並且在極少數情況下,這些類型暴露了類似IsDisposed標志的東西,因為它對於對象的消費者沒有任何意義。在大多數情況下。
當您知道世代號時,您可以根據以下因素做一些假設:
第0代。這是最年輕的一代,包含短期對象。 短期對象的示例是臨時變量。 垃圾收集在這一代中最常發生。 新分配的對象形成新一代對象,並且隱式生成0集合,除非它們是大對象,在這種情況下它們在第2代集合中的大對象堆上。 大多數對象在第0代被回收用於垃圾收集,並且不能存活到下一代。
第1代。此代包含短期對象,並用作短期對象和長期對象之間的緩沖區。
第2代。這一代包含長壽命的對象。 長期對象的一個示例是服務器應用程序中的對象,其中包含在進程持續時間內處於活動狀態的靜態數據
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.