2012-08-05 19 views
5

Sto utilizzando il Memory Management mentre restituisco i dati come di seguito.Utilizzo dell'istruzione durante la restituzione dei dati

private DataSet ReturnDs() 
{ 
    using (DataSet ds = new DataSet()) 
    { 
     return ds; 
    } 
} 

Query - C'è qualche problema a collocare la 'Usare' Dichiarazione mentre restituendo i dati? Sto ancora ottenendo lo schema completo così come i dati nella funzione di ricezione?

+2

Se si desidera restituire un oggetto, perché si desidera smaltirlo? –

+0

@Mert - Voglio sapere qual è il danno? C'è qualche perdita nei dati? Ho verificato che va bene ... La mia domanda è - c'è qualcosa di non vantaggioso che mi manca? –

+0

Hai verificato? Bello. Troppo poche persone effettivamente dimostrano il loro codice con metodi formali :) – Joey

risposta

4

Questo è sicuramente uno schema errato. L'unica ragione per cui sta funzionando ora è che DataSet.Dispose() è in realtà un manichino.

using (DataSet ds = new DataSet()) 
{ 
    return ds; 
} // there is a ds.Dispose() here but it does nothing. 

Se si sostituisce il DataSet con ad esempio un quadro Enitity DbContext allora non vedrebbe alcun dato in funzione chiamante.

+0

grazie per il tuo supporto .. puoi spiegare perché? –

+0

+1 Qualsiasi oggetto che effettivamente fa qualcosa di significativo nel suo metodo 'Dispose' apparirebbe" non valido "nel metodo di chiamata. –

+0

@HenkHolterman - puoi per favore condividere un link per spiegare ** c'è un ds.Dispose() qui ma non fa nulla **. –

0

Non sono sicuro di quale sia esattamente la tua domanda.

Una volta che il metodo è terminato con il riavvio di qualcosa, verrà chiamato automaticamente ds.Dispose().

Ciò significa che il DataSet restituito dal metodo sarà già eliminato quando il metodo di chiamata lo riceve.

0

come commento Mert, si noti che si sta eliminando l'oggetto che si desidera restituire. ma fondamentalmente, l'utilizzo è in realtà un tentativo/finalmente e il dispose sarà chiamato il metodo di ritorno. L'effetto dipende dall'implementazione IDisposable per ciascun tipo. di solito, non si suppone di disporre (uccidere) l'entità che si restituisce al chiamante che probabilmente lo userà.

+0

»esci dal campo di applicazione« .. Non penso che questa affermazione abbia senso qui. – Joey

2

Utilizzare l'istruzione using nel metodo chiamante, non il metodo che restituisce l'oggetto.

public void Caller() 
{ 
    using(DataSet ds = GetDataSet()) 
    { 
    // code here 
    } 
} 

public DataSet GetDataSet() 
{ 
    // don't use a using statement here 
    return ds; 
} 

La dichiarazione using è fondamentalmente lo stesso di fare questo:

DataSet ds = null; 
try 
{ 
    // code here 
} 
finally 
{ 
    if(ds != null) 
    { 
    ds.Dispose(); 
    ds = null; 
    } 
} 

Quindi, se si è utilizzato una dichiarazione using in un metodo che dovrebbe restituire l'oggetto nella dichiarazione using, sarebbe restituisce un oggetto Disposed (vale a dire flusso chiuso, dataset chiuso, ecc ...) che significa che alcuni degli oggetti interni potrebbero essere nulli o chiusi. In altre parole, tutte le risorse interne verrebbero eliminate, il che è lo scopo di implementare IDisposable in primo luogo. Se l'applicazione si basava su alcune di queste risorse interne per essere disponibili, ad esempio quando si utilizza un oggetto Stream, si genera un'eccezione.

Ricorda inoltre che non tutti i blocchi finally sono scritti nello stesso modo. Ricordate, IDispoable è stato implementato per ripulire qualsiasi risorsa INTERNA e oggetti non gestiti. Tali risorse interne potrebbero non essere necessarie al di fuori dell'istruzione using, quindi a volte è possibile utilizzare l'istruzione using come potrebbe sembrare funzionare correttamente, ma non è consigliabile, e sicuramente non funzionerà con tutti gli oggetti. Se Microsoft ha deciso di modificare l'oggetto DataSet in una versione futura, eliminando qualcosa di vitale per l'applicazione, il codice funzionante improvvisamente smetterebbe di funzionare.

+0

puoi spiegare perché? –

+0

@RGI - risposta aggiornata. –

+0

A downvote ?? In che modo questa risposta non è utile ?? –

4

In generale, lo smaltimento di un oggetto che si sta per restituire è un errore: il proprio codice non è stato completato con quell'oggetto e si passerà un oggetto rotto al chiamante.

In effetti, non lo è Dispose() che significa: non utilizzare using su un oggetto che si desidera restituire.Spetta al chiamante disporlo: sono i proprietari ora. Naturalmente, questo dovrebbe idealmente essere documentato nell'API.

Più in generale, tuttavia, è necessario pensare anche alle eccezioni. Cosa succede se lo metodo errori? Per scenari complessi, potrebbe essere necessario:

SomeType foo = null; 
try { 
    // initialize and populate foo - this could error half-way through 
    return foo; 
} catch { 
    if(foo != null) foo.Dispose(); 
    throw; 
} 

per garantire che l'oggetto sia disposto correttamente nel caso di errore.

+0

+1 Perché stai dicendo la stessa cosa di Henk. Inoltre, in senso stretto non è un errore, è solo inutile e priva di significato restituire ciò che può (e generalmente lo sarà) essere un oggetto morto per un chiamante. –

+0

Non ricevo alcun errore ... –

+0

@RGI perché per DataSet, Dispose è un no-op: http://stackoverflow.com/questions/913228/should-i-dispose-dataset-and-datatable E quindi perché ho risposto * nel caso generale *. Tuttavia, ciò che stai facendo è confuso e potrebbe portare a errori per qualsiasi altro tipo. Non farlo –