2011-01-06 17 views
6

Powiel możliwe:
What is the C# Using block and why should I use it?Czy używasz lepszego?

Moje pytanie: Czy za pomocą using(a){do something with a} lepiej niż oświadczając, 'A' i używając go w ten sposób. tj.: bezpieczniej, szybciej, ...

patrz przykłady dla wyjaśnienia.

Przykład 1: (bez użycia)

StreamWriter sw; 
string line; 
sw = new StreamWriter("D:\\NewCon.xml"); 
sw.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"); 
sw.WriteLine("<config>"); 
for (int i = 0; i >=36; i++) 
{ 
    line = ""; 
    line = "<" + xmlnodes[i] + ">"; 
    line += vals[i]; 
    line += "</" + xmlnodes[i] + ">"; 
    sw.WriteLine(line); 
} 
sw.WriteLine("</config>"); 
sw.Close(); 
sw.Dispose();  

Przykład 2 (z wykorzystaniem)

string line;  
using (sw = new StreamWriter("D:\\NewCon.xml")) 
{ 
    sw.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"); 
    sw.WriteLine("<config>"); 
    for (int i = 0; i >= 36; i++) 
    { 
     line = ""; 
     line = "<" + xmlnodes[i] + ">"; 
     line += vals[i]; 
     line += "</" + xmlnodes[i] + ">"; 
     sw.WriteLine(line); 
    } 
    sw.WriteLine("</config>"); 
} 

Odpowiedz

11

stosując (a) {coś z A}

Oznacza to, że gdy blok kodu zostanie wykonany za pomocą a, program wywoła a.Dispose. Wiesz, że nawet w przypadku wyjątku, zostanie wywołana Dispose. Zasadniczo robi się:

var a = IDisposable_Something; 
try{.....}finally{a.Dispose();} 

Czy to jest bardziej bezpieczne ... niezupełnie, ale nie o to chodzi. Chodzi o to, aby upewnić się, że zasoby, które należy oczyścić, są wykonywane zaraz po zakończeniu programu.

Problem z twoim pierwszym przykładem polega na tym, że jeśli gdzieś wzdłuż linii zostanie wyrzucony wyjątek, nie dojdzie do metody Dispose(). Druga wola. Zawsze chcesz zadbać o to, aby Dispose został wywołany, jeśli istnieje, ponieważ istnieje możliwość, że klasy IDisposable nie zostaną poprawnie napisane i nie będzie zawierał kodu, który zapewni, że niezarządzane zasoby zostaną wyczyszczone, nawet jeśli Dispose() nie jest wywoływany (zazwyczaj odbywa się to w finalizatorze). LInk to Dispose Pattern.

Jedyny przypadek, w którym kiedykolwiek widziałem, gdzie implementowanie przy użyciu może być trudne, dotyczy proxy usługi WCF (i można obejść ten problem). Występuje błąd, w którym jeśli proxy czasami zgłasza wyjątek, spowoduje to kolejny wyjątek w metodzie Dispose().

http://blogs.msdn.com/b/jjameson/archive/2010/03/18/avoiding-problems-with-the-using-statement-and-wcf-service-proxies.aspx

Poza tym należy generalnie spróbować położyć IDisposable obiektu w użyciu instrukcji.

+0

Świetna odpowiedź, dziękuję za wyczyszczenie tego dla mnie! –

0

Jest bezpieczniejszy w tym sensie, że zazwyczaj nie zapomina się o dysponowaniu zasobami, szczególnie w przypadku wyjątku (obecnie nie ma żadnego kodu).

Jest bardziej zwięzły i idiomatyczny, ponieważ używa mniej linii kodu, a zamiar kodu staje się znacznie wyraźniejszy.

Więc tak:

StreamWriter sw; 
try 
{ 
sw = new StreamWriter("D:\\epkDATA\\NewCon.xml"); 
... 
} 
finally 
{ 
sw.Dispose(); 
} 

odpowiada:

using(StreamWriter sw = new StreamWriter("D:\\epkDATA\\NewCon.xml")) 
{ 
... 
} 
6

Jeśli jest wyjątek w swoim pierwszym przykładzie to zasób nie zostaną usunięte.

Użycie using zapewnia, że ​​zasób jest usuwany nawet po zgłoszeniu wyjątku.

+0

Prawie dokładnie to, co miałem w moim polu "Odpowiedź", zanim trafiłem w nowe odpowiedzi. – Rangoric

1

Przede wszystkim kod w przykładzie 1, powinny być opakowane w try/finally zablokować, aby być funkcjonalnie równoważny z kodem w przykładzie 2.

Powiedział, że zawsze lubiłem „za pomocą” bloki dla takiego kodu. Myślę, że generalnie prowadzi to do bardziej czytelnego kodu. Jeśli chodzi o bezpieczeństwo lub wydajność, nie zobaczysz dużej różnicy między przykładem 1 a przykładem 2, pod warunkiem, że użyjesz bloku try/finally w pierwszym przykładzie!

0

Używanie jest bezpieczniejsze, ponieważ masz gwarantowane zwolnienie zasobów zadeklarowane przy użyciu (...) nawiasów klamrowych, nawet gdy wystąpił błąd lub nieoczekiwane wyjście.

0

Dodano do poprzednich odpowiedzi, i najbardziej importabt część, jeśli wystąpi wyjątek, wywołanie dispose() jest gwarantowana.

2

Przykład 1 nigdy nie powinien być wykonywany. Jeśli zostanie zgłoszony wyjątek, twoje wywołanie Dispose() nigdy nie nastąpi, co może być złe. using gwarantuje wykonanie Dispose(). Jedyną dobrą alternatywą dla przykładu 1 (oprócz using) byłoby:

var iDisposableObject = new YourDisposableConstructor(); 
try 
{ 
    // some code 
} 
finally 
{ 
    iDisposableObject.Dispose(); 
} 
0

jeśli ClassA dziedziczą IDisposing.A „za” wzorzec jest równa co następuje:

IDisposable iDisposableObject = new YourDisposableConstructor(); 
try 
{ 
    // some code 
} 
finally 
{ 
    iDisposableObject.Dispose(); 
} 

więc lepiej korzystania wzorzec używania

Powiązane problemy