2009-06-08 11 views
26

Ponieważ instrukcja C# używająca jest tylko syntaktycznym cukrem dla try/finally {dispose} dlaczego akceptuje wiele obiektów TYLKO JEŚLI JEST TO TYM SAMEGO TYPU?przy użyciu różnych typów w instrukcji using (C#)

Nie rozumiem tego, ponieważ wszystko, co musi być, jest IDisposable. Jeśli wszystkie implementują IDisposable, powinno być dobrze, ale tak nie jest.

Konkretnie jestem przyzwyczajony do pisania

using (var cmd = new SqlCommand()) 
{ 
    using (cmd.Connection) 
    { 
     // code 
    } 
} 

które kompaktowy do:

using (var cmd = new SqlCommand()) 
using (cmd.Connection) 
{ 
    // code 
} 

i chciałbym kompaktowy ponadto do:

using(var cmd = new SqlCommand(), var con = cmd.Connection) 
{ 
    // code 
} 

ale nie mogę . Mógłbym prawdopodobnie, niektórzy twierdzą, napisać:

using((var cmd = new SqlCommand()).Connection) 
{ 
    // code 
} 

ponieważ wszystko muszę wyrzucać jest związek, a nie polecenie, ale to prócz tego punktu.

+2

Czy uczę się czegoś nowego tutaj? Co oznacza druga, nieprzypisana instrukcja użycia w najwyższym przykładzie? Czy ten przedmiot staje się zakresem? – spender

+0

@spender: argumentem użycia musi być wyrażenie, które można przekonwertować na IDisposable. Deklaracja jest (tylko jednym) takim wyrażeniem. –

+0

@spender: Tak, ty (prawdopodobnie) nauczyłeś się czegoś nowego. Składnia użycia używa instrukcji (IDisposableInstance) ;. Tak jak Henk Holterman powiedział, że przydział jest operacją, której wynik (często nieużywany, ale tutaj użyty) jest wartością przypisaną. –

Odpowiedz

20

Można to zrobić choć:

using (IDisposable cmd = new SqlCommand(), con = (cmd as SqlCommand).Connection) 
{ 
    var command = (cmd as SqlCommand); 
    var connection = (con as SqlConnection); 
    //code 
} 

Być może byłoby satysfakcjonujące dla Ciebie.

+0

Ładnie wygląda, dopóki nie rozwiniesz // linii kodu –

+1

@Henk Nie podążam za tobą. – Joseph

+0

To jest najbliższe obejście, jakie do tej pory widziałem. Jednak będę musiał rzucić cmd z powrotem do SqlCommand w bloku, aby nim manipulować. To samo z "con", które będę musiał otworzyć, aby wykonać swoją pracę. –

5

Inne deklaracje zmiennych w języku C# umożliwiają tylko zadeklarowanie wielu zmiennych tego samego typu w tej samej instrukcji; Nie rozumiem, dlaczego nagłówki powinny być inne.

+0

Tak i nie, nic Cię nie powstrzymuje: IComparable c1, c2, a później w twoim kodzie mają c1 i c2 być całkowicie różnymi rodzajami betonu, które implementują ICom przypowieść. To właśnie wskazuje OP, wszystko, co muszą być IDisposable ... – BFree

+0

Oczywiście, ale możesz to zrobić również za pomocą instrukcji IDisposable, na przykład, jest to legalne: using (IDisposable a = new SqlCommand() , b = new SqlConnection()) – mquander

+0

BFree, dokładnie tak mówi mquander, prawda? using (IDisposable x = new Connection(), y = new Command()) działałoby, ale jest raczej bezużyteczne. Typ referencji się liczy. –

16

Nie ma szczególnie dobrego technicznego uzasadnienia; moglibyśmy wymyślić składnię, która dopuszczała wiele deklaracji typów niejednorodnych. Biorąc pod uwagę, że tego nie zrobiliśmy i istnieje już doskonale dobry, jasny, zrozumiały i dość zwięzły mechanizm deklarowania zagnieżdżenia przy użyciu bloków różnych typów, prawdopodobnie nie będziemy dodawać nowego cukru syntaktycznego tylko po to, aby zapisać kilka naciśnięć klawiszy.

+12

Och, widzę ... aby uchronić nas przed cukrzycą składniową, nie dodamy więcej cukru syntaktycznego: P –

+0

cukrzyca składniowa .. muahah :) – VVS

+2

Innymi słowy. Meh! * Wzrusza ramionami * –

0

Mój osobisty sposób korzystania z tego może pasowały:

private const string SQL_CONNECTION = "Your Connection String Here"; 

private void Test(string sqlCmd) 
{ 
    using (var cmd = new SqlCommand(sqlCmd, new SqlConnection(SQL_CONNECTION))) 
    { 
    cmd.Connection.Open(); 
    cmd.ExecuteNonQuery(); 
    cmd.Connection.Close(); 
    // Close() is not really necessary. 
    // Dispose will Close the connection. 
    } 
} 

Nie, to nie dwa przypadki klauzuli w jednej linii using, ale to jest tak zwarta, jak starają się dostać w swoje przykład.

Co więcej, można zrobić to jeszcze bardziej kompaktowy i przyjazny obracając swój ciąg połączenia do prywatnej posesji programista:

private SqlConnection OpenConnection 
{ 
    get { 
    var con = new SqlConnection(SQL_CONNECTION); 
    con.Open(); 
    return con; 
    } 
} 

teraz, że pierwszy bit kodu powyżej w Test() może być skrócony do następujących :

private void Test2(string sqlCmd) 
{ 
    using (var cmd = new SqlCommand(sqlCmd, OpenConnection)) 
    { 
    cmd.ExecuteNonQuery(); 
    } 
} 

To sprawia, że ​​kodowanie jest bardzo przyjemne.

Powiązane problemy