2011-01-14 16 views
9

Zobaczyć to. Dlaczego wyraźna obsada do IDisposable? Czy jest to skrót, aby upewnić się, że IDisposable jest wywoływane przy wychodzeniu z bloku użytego?Typ odlewania do IDisposable - Dlaczego?

using (proxy as IDisposable) 
{ 
    string s = proxy.Stuff()          
} 

Odpowiedz

25

Ta "sztuczka", jeśli możesz to tak nazwać, najprawdopodobniej jest spowodowana tym, że proxy jest typu, którego kompilator nie może zweryfikować, naprawdę implementuje IDisposable.

Zaletą dyrektywy using, jest to, że jeśli parametr do niego jest null, to nie wezwanie do Dispose zostaną wykonane po wyjściu z zakresu rachunku using.

Więc masz kod pokazany jest rzeczywiście krótki ręka dla:

var disposable = proxy as IDisposable; 
try 
{ 
    string s = proxy.Stuff(); 
} 
finally 
{ 
    if (disposable != null) 
     disposable.Dispose(); 
} 

Innymi słowy, to mówi „jeśli ten obiekt implementuje IDisposable, muszę pozbyć się go, kiedy skończę z kolejny fragment kodu. "

+0

+1 dla "jeśli ten obiekt implementuje IDisposable ..." – Justin

4

Jest to konieczne, gdyż oświadczenie using jest wyraźnie związany z interfejsem IDisposable, per the MSDN docs

zapewnia wygodną składnię, która zapewnia właściwe wykorzystanie obiektów IDisposable.

edycja: THE C# language spec (. S 8,13) posiada trzy możliwe rozszerzenia cukru składniowej przez using komunikat to:

A z użyciem instrukcji postaci

using (ResourceType resource = expression) statement 

odpowiada jednemu z trzech możliwych rozszerzeń. Kiedy ResourceType jest typem wartości nie pustych, ekspansja jest

{ 
    ResourceType resource = expression; 
    try { 
     statement; 
    } 
    finally { 
     ((IDisposable)resource).Dispose(); 
    } 
} 

W przeciwnym razie, gdy ResourceType jest pustych typ wartości lub typ referencyjny inne niż dynamiczna ekspansja jest

{ 
    ResourceType resource = expression; 
    try { 
     statement; 
    } 
    finally { 
     if (resource != null) ((IDisposable)resource).Dispose(); 
    } 
} 

W przeciwnym razie, gdy ResourceType jest dynamiczna ekspansja jest

{ 
    ResourceType resource = expression; 
    IDisposable d = (IDisposable)resource; 
    try { 
     statement; 
    } 
    finally { 
     if (d != null) d.Dispose(); 
    } 
} 

Należy zauważyć, że w każdym z tych rozszerzeń obsada jest wykonywana tak, jak pierwotnie stwierdzono, as IDisposable jest niepotrzebne.

+2

Co jeśli "proxy" jest obiektem, który programista "wie" implementuje IDisposable, ale kompilator nie może go zweryfikować? Dlaczego więc obsada nie byłaby konieczna? –

+0

Tak, jeśli istnieje jakikolwiek powód, dla którego jest jasne dla czytelnika, że ​​'proxy' rozszerza IDisposable – Will

+0

Tak długo, jak jego proxy nie jest proxy WCF, w takim przypadku nie jest bezpiecznie używać bloku. Ale to już inny temat. –

3

Może to być wymagane, jeśli otrzymasz instancję proxy skądś, a jej typ statyczny nie implementuje IDisposable, ale wiesz, że prawdziwy typ może zrobić i chcesz się upewnić, że zostanie usunięty, np.

public class Proxy : ISomeInterface, IDisposable 
{ 
    ... 
} 

private ISomeInterface Create() { ... } 

ISomeInterface proxy = Create(); 

//won't compile without `as` 
using(proxy as IDisposable) 
{ 
    ... 
} 
+0

+1 Możesz również mieć podobny przykład do generycznych. –

Powiązane problemy