Soru C # nesnelerini el ile yok et


C # (Java ve C ++ arkaplanından) öğrenme konusunda oldukça yeniyim ve manuel çöp imhası hakkında bir sorum var: C # içindeki bir nesneyi manuel olarak imha etmek bile mümkün mü? Hakkında biliyorum IDisposable Arayüz, ama yazmadığım bir sınıfla uğraştığımı ve bunu uygulamadığını varsayalım? Bu olmazdı .Dispose() yöntem, öyle ki ve using { } çıktı ve .Finalize her zaman ya protected veya private Yani bu da bir seçenek değil.

(Sadece ne olduğunu öğrenmeye çalışıyorum mümkün bu durumda C # içinde. Sanırım her şey başaramazsa miras almak varsayımsal ImNotDisposable böylece sınıf yapar IDisposable uygulamak.)


25
2017-12-31 21:54


Menşei


Belki de şu soruyu açıklığa kavuşturmalısınız: Bir nesneyi tamamen tahsis etmek mi yoksa sadece tahrip edici yöntemini uygulamak ve nesnenin kaynaklarını temizlemek mi istiyorsunuz (sadece)? - David R Tribble
Birinin diğerini ima ettiğine inanıyorum, ama aklımda olan şey bir nesnenin sahip olduğu ~ ClassName () yöntemini 'tetiklemenin' bir yoluydu. - East of Nowhere
Sonuç olarak, GC, hemen hemen hepsi ya da hiç olmayan Collect () yöntemine sahiptir ve belirli bir nesneyi hedeflemek için herhangi bir yol yoktur. Yakaladım. :) - East of Nowhere


Cevaplar:


Elle yok. Net nesneler. Yönetilen bir ortam olmakla ilgili olan şey budur.

Aslında, eğer nesne gerçekten ulaşılabilir ise, yani, GC'ye hangi nesneyi yok etmek istediğinizi söylemek için kullanabileceğiniz bir referansınız var demektir, bu nesneyi toplamak imkansız olacaktır. GC olacak asla Hala ulaşılabilir olan herhangi bir nesneyi toplamak.

Ne yapabileceğiniz çağrıdır GC.Collect() Genel bir koleksiyonu zorlamak. Ancak, bu neredeyse hiç iyi bir fikir değildir.

Bunun yerine, muhtemelen daha iyi taklit Yönetilmeyen kaynakları kullanmayan ve programınızdaki diğer herhangi bir nesne tarafından erişilemeyen herhangi bir nesne hemen yok edilir. Bunun gerçekleşmediğini biliyorum, ama bu noktada nesne, tıpkı diğerleri gibi sadece bir hafıza bloğu; bunu geri alamazsın ve sonunda toplanacak, bu yüzden senin için de ölmüş olabilir.

Hakkında son bir not IDisposable. Sadece sarmak için kullanmalısınız yönetilmeyen kaynaklar: Soketler, veritabanı bağlantıları, gdi nesneleri, vb. ve zaman zaman olay / delege aboneliği gibi şeyler.


25
2017-12-31 21:59



Ayrıca, harici nesnelere bağlandığım tüm olayların bağlantısını kaldırmak için kullanıyorum. Bunu yapmazsanız, nesne, harici bir nesne olana kadar, uygulamanın ömrü boyunca olabilecek olan bellekten kaldırılmaz. - Mongus Pong
@MongusPong: Dispose çok önemlidir, fakat nesneleri "yok etmemektedir" - bunun yerine, hizmetlerinin artık gerekli olmadıklarını bildirir, böylece diğer varlıklar (kendi adlarına hareket eden (varsa) bildirilebilir. onların hizmetler artık gerekli değildir. - supercat
Genel ifadeye tamamen katılmıyorum "Sadece yönetilmeyen kaynakları sarmak için kullanmalısınız". Bilinçli bir bilgelik olduğunu biliyorum, ama bellek sızıntısı sorunları yaşarsanız, öğeleri tek kullanımlık yapmak çok iyidir. İyi bir hafıza izleme uygulaması olmanın nedeni, size imha edilmiş, ancak henüz tahrip edilmemiş nesneleri gösterebilmektir. Yıkım için neyi işaretlediğinizi açıkça gösterir, ancak tahrip edilmemiştir. Bunun yanı sıra, size iyi bir fırsat ve olay işleyicileri ve böylece ağın düzgün bir şekilde kırılmasını sağlayacak şekilde takmak için standart bir yer sunar. - Melbourne Developer


Nesne ulaşılamıyorsa, arayabilirsin GC.Collect() ve nesne yok edilecek. Kavramı IDisposable CLR ile hiçbir ilgisi yoktur ve çoğunlukla gerçekleştirmek için uygulamak için kullanıcı kodu için ek bertaraf mantığı. Bir nesnedeki Dispose () öğesini çağırmak, nesnenin kendisini bellekten kurtarmayacaktır, ancak bu nesnenin başvurduğu kaynakları çok iyi bertaraf edebilir.

Bunu söyleyeceğim bir şey olsa da bunu eklemeliyim, uygulamaların% 99.9999'unda asla aramamalısınız GC.Collect() çünkü sık sık indirgemek Uygulamanızın performansını iyileştirmek yerine.


7
2017-12-31 21:57



çağrı GC.Collect() Yapmanız gereken bir şey değil, çok iyi sebep. - Sander Rijken
Bu, nesneye yapılan göndermelerle ilgili değil - erişilebilirlik hakkında (ki bundan bahsederim). - Eilon
A nesnesi, b nesnesine bir başvuru içeriyorsa ve b, a öğesine bir başvuru içeriyorsa, her ikisi de a ve b'ye başvurulur (AKA, bir dairesel başvuru). Ancak, hiç kimsenin ya a ya da b'ye atıfta bulunmaması durumunda, ne ulaşılamaz, ne de çöp toplayıcı onları yok edecektir (nihayetinde). - Eilon
Zaman, GC performansında rol oynar. Her şey ne sıklıkta ve ne kadar bellek ayrıldığına bağlıdır. Aramaları birbirinden ayırmak aslında bir anlam ifade etmiyor - eğer normalde tetiklenen bir GC oluşmamışsa, nesneyi gereksiz yere nesneyi performansı etkileyen yüksek nesillere yükseltiyor olabilirsiniz. Özellikle uzun süren uygulama ve servislerde. - Josh
@Cecil: EVET, performansa zarar verebilir. Bir koleksiyonun toplanması için bir şey olmaması veya koleksiyonunuz meşgul olduğunda bir koleksiyonun zorlanması durumunda bile koleksiyonunuz için durmanız gerektiğini düşünün. Daha da kötüsü, çöp toplayıcı nesillerdir, nesneleri gerçekten daha uzun bir yaşam nesline taşımak için zorlayabilirsiniz. - Joel Coehoorn


Çöp toplanmasını tetikleyebilmenize rağmen (tüm nesiller için GC'yi tetiklemeniz gerekir, çünkü kesinleştirilebilir nesneyi hangi nesilde olduğundan emin olamazsınız) belirli bir nesnenin kesinleştirilmesini zorunlu olarak zorlayamazsınız. Çöp toplayıcının nasıl çalıştığıyla ilgili varsayımlara güvenebilirsiniz.

Furtnermore, sonuçlandırma kendi iş parçasında gerçekleştiğinden, aramalısın WaitForPendingFinalizers çöp toplama tetikledikten sonra.

GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();

Başkaları tarafından da belirtildiği gibi, bu aslında uygulamanızın performansını olumsuz yönde etkileyebilir çünkü gereksiz yere GC'yi çağırmak, kısa ömürlü nesnelere toplanması daha pahalı olan ve daha az sıklıkla toplanan daha yüksek nesillere dönüşebilir.

Genel olarak konuşmak gerekirse, bir finalleştirici (yıkıcı) uygulayan ve kimliğini yerine getirmeyen bir sınıf çatırdamaktadır. Ve her ne kadar IDisposable'ı uygulayan her şey, onun finalizer mantığını çağırması ve çöp toplamada son halini almasını istemelidir.

Jeff Richter geçenlerde güzel bir hile yayınladı çöp toplama gerçekleştiğinde bir bildirim alma.

Bir başka harika yazı Çöp Toplayıcı Temelleri ve Performans İpuçları Rico Mariani (MSFT) tarafından


7
2017-12-31 22:06





Hayır, belirli bir nesneyi yok edemezsin.

Nesnelerin yok edilmesini sağlayacak çöp toplayıcısını çağırmak mümkün, ama neredeyse hiçbir zaman iyi bir fikir değil.


6
2017-12-31 21:58





Sen kutu Çöp toplayıcısını yok etmek istediğiniz değişkenin kapsam dışı kalmasından sonra çalışmaya zorlayın, ancak normalde bunu yapmak istemezsiniz, çünkü çöp toplayıcı kendi işini yapmak için bırakılırsa daha verimli olur.

Zorla çöp toplama ile yapılabilir GC.Collectama yapma. 10 yıldır bir .NET geliştiricisi olarak, buna hiç ihtiyacım olmadı.


4
2017-12-31 21:59





Bir nesneyi deterministik bir şekilde yok etmek mümkün değildir. CLR, işaretli nesnenin ne zaman yeniden kazanılacağını belirler. Bu, bir nesneyi yeniden isimlendirmek için işaretleyebilir ve yönetilen ve yönetilmeyen kaynakların bertaraf edilmesini (IDisposable modelini uygulayarak) sağladığınızdan emin olmanıza rağmen, belleğin bırakıldığı gerçek sürenin CLR'ye kadar olduğu anlamına gelir. Bu, aslında bir şeyi silebileceğiniz C ++ 'dan farklıdır ve daha sonra serbest bırakılır.

Mutlu kodlama,

Scott


2
2017-12-31 22:01



Atılan çağrı, nesneyi geri alınabilir olarak işaretlemez, yalnızca, çöp toplayıcının gelmesini beklemek ve nesneyi nihai hale getirme zamanına karar vermek yerine, onlarla bittiğinde, veritabanı bağlantıları gibi sınırlı kaynakları serbest bırakmanızı sağlar. - Paolo


Sen olamaz "C ++ sil" gibi bir nesneyi el ile yok edin, yapabileceğiniz her şey yalnızca nesnenin aldığı tüm özel kaynakları kapatın ve bu nesneye yapılan tüm referansları boşaltır, böylece GC bunu toplayabilir, ayrıca GC.Collect () 'i çağırmayın. Kendiniz tarafından GC süreci pahalıdır, çünkü diğer tüm konuları askıya alarak nesneleri bellekten güvenli bir şekilde toplayabilir, böylece yalnızca GC'ye güvenebilirsiniz ve gerektiğinde başlayacaktır.


2
2017-12-31 22:02



Peki hiçbir zaman hiçbir referans değişkenini myObj = null gibi boş bir değere atamazdım; Sadece kapsam dışına çıkmalarına izin verdim. - East of Nowhere
Katılıyorum, eğer mümkünse bunu yapmayı deneyeceğim - bashmohandes


Sınıf matrisiniz olduğunu ve bir matris ve bMatrix olmak üzere iki matris nesnesi oluşturduğunuzu varsayalım. C # 'da bir nesneyi el ile yok edebilir (sonlandırabilirsiniz):

aMatrix = NULL;

GC.Collect ();

Çöp toplayıcı, aMatrix'inizin NULL olduğunu fark edecek ve onu yok edecektir. Bunun iyi bir fikir olup olmadığı farklı bir hikaye.


0
2017-08-14 11:40