İmha edilecek hiçbir şeyin olmadığı bir bağlamda 'kullanma' uygun mudur?


9

C # 'da usingifade, çöp toplayıcısını beklemeden kaynakları belirleyici bir şekilde atmak için kullanılır. Örneğin, aşağıdakiler için kullanılabilir:

  • SQL komutlarını veya bağlantılarını imha edin,

  • Akışları kapatın, temeldeki kaynağı bir dosya gibi serbest bırakın,

  • Ücretsiz GDI + öğeleri,

  • vb.

Bertaraf edilecek usinghiçbir şeyin olmadığı durumlarda daha fazla kullanıldığını fark ettim , ancak arayanın usingiki ayrı komut yerine bir blok yazmasının daha uygun olduğu yerlerde .

Örnekler:

  • Stack Overflow ekibi tarafından yazılan MiniProfiler , usingblokları profile göstermek için kullanır :

    using (profiler.Step("Name goes here"))
    {
        this.DoSomethingUseful(i - 1);
    }
    

    Alternatif bir yaklaşım iki bloğa sahip olmak olacaktır:

    var p = profiler.Start("Name goes here");
    this.DoSomethingUseful(i - 1);
    profiler.Stop(p);
    

    Başka bir yaklaşım eylemleri kullanmak olacaktır:

    profiler.Step("Name goes here", () => this.DoSomethingUseful(i - 1));
  • ASP.NET MVC ayrıca usingformlar için seçti :

    <% using (Html.BeginForm())
       { %>
           <label for="firstName">Name:</label>
           <%= Html.TextBox("name")%>
           <input type="submit" value="Save" />    
    <% } %>
    

Böyle bir kullanım uygun mu? Birkaç dezavantaj olduğu göz önüne alındığında, nasıl gerekçelendirilir:

  • Yeni başlayanlar kaybolacaktı, çünkü bu tür kullanım kitaplarda ve dil spesifikasyonlarında açıklananla uyuşmuyor,

  • Kod anlamlı olmalıdır. Burada, ifade etme sıkıntısı çekiyor, çünkü uygun kullanımı, usingarkasında, çöp toplayıcısını beklemeden serbest bırakılması gereken bir akış, ağ bağlantısı veya veritabanı gibi bir kaynak olduğunu göstermek.


2
İki ayrı ifadeye sahip olma yaklaşımı, saf kaynak yönetimi ile aynı sorundan muzdariptir using: İkinci ifadenin (örn. profiler.Stop(p)) İstisnalar ve kontrol akışı karşısında yürütüleceği garanti edilmez.

1
@delnan: MiniProfiler'in neden ikinci yaklaşımı önlediğini açıklıyor. Ancak ikincisinden her durumda kaçınılmalıdır, çünkü yazmak ve korumak zordur.
Arseni Mourzenko



Yanıtlar:


7

Son ifadeniz - "Kullanmanın uygun kullanımının arkasında, çöp toplayıcısını beklemeden yayınlanması gereken bir akış, ağ bağlantısı veya veritabanı gibi bir kaynak olduğunu" göstermek ve bunun nedeninin IDisposable arabiriminin belgelerinde verilmiştir: http://msdn.microsoft.com/en-us/library/system.idisposable.aspx

Bu arabirimin birincil kullanımı, yönetilmeyen kaynakları serbest bırakmaktır.

Bu nedenle, sınıfınız yönetilmeyen herhangi bir kaynak kullanıyorsa, GC'nin ne zaman olmasını isteyebileceğiniz veya istemeyeceğiniz önemli değildir - yönetilmeyen kaynaklar GC'ed olmadığı için GC ile hiçbir ilgisi yoktur ( https: // stackoverflow. com.tr / sorular / 3607213 / yönetilen-vs-yönetilmeyen kaynaklar-net-in ) anlamına gelir ).

"Kullanarak" amacı GC bekleyen önlemek için değil Yani, bu yönetilmeyen kaynaklarının salımını zorlamak için var şimdi sınıf örneği kapsam dışına gider ve 's Tamamladı çağrılmadan önce. Bu açık olması gereken nedenlerden dolayı önemlidir - yönetilmeyen bir kaynak diğer yönetilmeyen kaynaklara bağımlı olabilir ve yanlış sırada atılırsa (veya sonlandırılırsa) Kötü Şeyler meydana gelebilir.

Eğer kullanma bloğunda örneklenen sınıf yönetilmeyen herhangi bir kaynak kullanıyorsa, o zaman cevap evettir - uygundur.

Bununla birlikte , IDisposable'ın yalnızca yönetilmeyen kaynakları serbest bırakmakla ilgili kurallara aykırı olmadığını unutmayın - sadece bu birincil amaçtır. Bu olabilir sınıfının yazarı belli bir zamanda oluyor ve ıdisposable bunun olmasına almanın bir yolu olabilir uygulamaya zorlamak istiyorum, ama olsun veya olmasın şık bir çözüm olduğunu bazı eylem olduğu durumda olması şeydir kutu yalnızca duruma göre yanıtlanmalıdır.

Hangisi "kullanma" nın kullanılması, sınıfın IDisposable'ı uyguladığını ima eder, bu nedenle kod ifadesini ihlal etmez; aslında neler olduğunu oldukça netleştirir.


"Bu arabirimin birincil kullanımı yönetilmeyen kaynakları serbest bırakmaktır." Microsoft'un belgelerinin bu noktada berbat olduğunu söylüyorum. Nasıl en Belki bu onlar FCL kullanmak, ancak uygulama geliştiricileri artık bir on yıl kadar yakın için çeşitli şeyleri için kullanıyorum - iyi nedenleriyle bazı, o kadar iyi değil nedenleriyle bazı. Ancak bu dokümanın yığınından alıntı yapmak OP'nin sorusuna hiç cevap vermiyor.
Jesse C. Slicer

1
İkinci son parama dikkat edin - birincil amacın tek amaç olması gerekmez . IDisposable herhangi bir nedenle uygulanabilir ve beklenen davranış ve kullanım stiline sahip bilinen bir arayüz sağlar, bu yüzden gördüğünüzde, örneğin kapsam dışına çıkabilmesi için olması gereken başka bir şey olduğunu bilirsiniz. Mesele şudur: IDisposable uygularsa, o zaman kullanmak uygundur; diğer her şey önsözdür.
Maximus Minimus

1
Temel olarak amacın GC'yi beklemekten kaçınmadığını, finalizörü beklemekten kaçındığını söylüyorsunuz. Ama farkı görmüyorum: finalizer GC tarafından çağırılıyor.
svick

GC belirleyici olmayan bir şekilde çalışır - ne zaman çağrılacağını bilmiyorsunuz. GC aynı zamanda sonlandırıcıyı çağırır, ancak kendini imha etmez - gerçek kaynağın kendisi GC'nin kontrolü dışındadır. (1) ile nesne doğru bir şekilde kapsamlandırılır ve (2) elden çıkarmanın bilinen bir noktada gerçekleştiği bilinmektedir - kullanım bloğunun kapsamından çıktığında, yönetilmeyen kaynak kaybolur (veya - en kötü durumda - teslim edilir) yok edecek başka bir şeye). Gerçekten, bu sadece nitpicking; belgeleri tekrarlayın, tekrarlanması gerekmiyor.
Maximus Minimus

8

Kullanımı usingbir Dispose()yöntemin varlığını ima eder . Diğer programcılar, nesnede böyle bir yöntemin var olduğunu varsayacaktır. Sonuç olarak, bir nesne tek kullanımlık değilse, usingüzerinde kullanmamalısınız .

Kod netliği kraldır. Nesneyi atlayın usingya IDisposableda nesneye uygulayın.

MiniProfiler using, profillenen kodu " çitlemek " için bir mekanizma olarak kullanıyor görünmektedir . Bunun bir değeri var; muhtemelen, MiniProfiler ya Dispose()bir zamanlayıcıyı durdurmak için çağırıyor ya da MiniProfiler nesnesi kapsam dışına çıktığında zamanlayıcı durduruluyor.

Daha genel olarak, bir usingtür sonlandırmanın otomatik olarak gerçekleşmesi gerektiğinde çağırırsınız. Belgeleri html.BeginForm, yöntem kullanıldığında devletler usingaçıklamada, kapanış vermektedir </form>sonunda etiketi usingbloğu.

Bu, onun hala istismar olmadığı anlamına gelmez.


4
Şimdiye kadar çok açık. Soru, OP'nin tanımladığı anlamda atması gereken bir şey olmamasına rağmen (ne zaman) uygulanması uygunsa IDisposable/ uygunsa Dispose()?

2
Bunu netleştirdiğimi düşündüm; bunun uygun olduğu bir zaman yoktur.
Robert Harvey

1
Anlatmak olduğu Disposeiçin gereklidir using(bakılmaksızın 's uygun olmadığına bakılmaksızın) hiç mantıklı. OP'nin örneklerinin hepsi geçerli Dispose, değil mi? Ve IIUC, soru, bu sınıfların Disposebaşka bir yöntem yerine ( Stop()MiniProfiler için olduğu gibi ) doğru olup olmadığıdır .

1
Evet, ama soru bu değil. Soru, bunun iyi bir fikir olup olmadığıdır.

2
@delnan: Yine, bunu netleştirdiğimi düşündüm. Kodunuzun amacını daha net hale getirirse, iyi bir fikirdir. Eğer değilse, değil.
Robert Harvey

1

usinghata ve istisna güvenlidir. Bu garantiler Dispose()programcı yapar herhangi bir hata aldırmaksızın çağrılır. İstisnaların yakalanmasına veya işlenmesine müdahale etmez, ancak Dispose()bir istisna atıldığında yöntem yığının üzerinde tekrarlı olarak yürütülür.

Uygulanan IDisposeancak bittiğinde atılacak hiçbir şeyleri olmayan nesneler . En iyi, gelecekteki tasarımlarını prova ediyorlar. Böylece, kaynak kodunuzu yeniden düzenlemenize gerek kalmaz, ileride bir şey atmaları gerekir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.