Perché un metodo che restituisce un bool / int e ha l'oggetto reale come parametro di output?

11

Vedo il seguente schema di codice dappertutto nel codebase della mia azienda (applicazione .NET 3.5):

bool Foo(int barID, out Baz bazObject) { 
    try { 
            // do stuff
            bazObject = someResponseObject;

            return true;
    }
    catch (Exception ex) { 
        // log error
        return false;
    }
}

// calling code
BazObject baz = new BazObject();
fooObject.Foo(barID, out baz);

if (baz != null) { 
    // do stuff with baz
}

Sto cercando di capire perché si dovrebbe fare questo invece di avere il metodo Foo semplicemente prendere l'ID e restituire un oggetto Baz , invece di restituire un valore che non è utilizzato e che ha il l'oggetto reale è un parametro ref o output.

C'è qualche vantaggio nascosto di questo stile di codifica che mi manca?

    
posta Wayne Molina 13.05.2011 - 15:52
fonte

5 risposte

11

Di solito usi quel modello in modo da poter scrivere un codice come questo:

if (Foo(barId, out bazObject))
{
  //DoStuff with bazobject
}

è usato nel CLR per TryGetValue nella classe del dizionario per esempio. Evita una certa ridondanza, ma i parametri di ref e out mi sono sempre sembrati un po 'disordinati

    
risposta data 13.05.2011 - 15:55
fonte
11

Questo è il vecchio codice di stile C, prima c'erano delle eccezioni. Il valore restituito indicava se il metodo aveva successo o meno, e se lo era, il parametro sarebbe stato riempito con il risultato.

In .net abbiamo eccezioni a tale scopo. Non ci dovrebbero essere motivi per seguire questo modello.

[modifica] Ci sono ovviamente implicazioni sulla performance nella gestione delle eccezioni. Forse questo ha qualcosa a che fare con questo. Tuttavia, in questo frammento di codice esiste già un'eccezione. Sarebbe più pulito lasciare che si muova nello stack fino a quando non viene catturato in un posto più appropriato.

    
risposta data 13.05.2011 - 15:56
fonte
2

Dato lo snippet di codice sembra assolutamente inutile. Per me il modello di codice iniziale suggerirebbe che null per BazObject sarebbe un caso accettabile e il ritorno bool è una misura per determinare in modo sicuro un caso di errore. Se il seguente codice era:

// calling code
BazObject baz = new BazObject();
bool result = fooObject.Foo(barID, out baz);

if (result) { 
    // do stuff with baz
    // where baz may be 
    // null without a 
    // thrown exception
}

Questo avrebbe più senso per me farlo in questo modo. Forse questo è un metodo che qualcuno prima stava usando per garantire che baz venisse passato per riferimento senza capire come i parametri oggetto funzionassero effettivamente in C #.

    
risposta data 13.05.2011 - 15:57
fonte
1

A volte questo schema è utile quando a te, il chiamante, non dovrebbe importare se il tipo restituito è un riferimento o un tipo di valore. Se chiami un metodo di questo tipo per recuperare un tipo di valore, quel tipo di valore avrà bisogno di un valore non valido stabilito (ad es. Double.NaN), o ti servirà un altro modo per determinare il successo.

    
risposta data 19.05.2011 - 09:28
fonte
0

L'idea è di restituire un valore che indica se il processo ha avuto successo, consentendo un codice come questo:

Baz b;
if (fooObject.foo(id, out b)) {
   // do something with b
}
else {
   Error.screamAndRun("object lookup/whatever failed! AAaAAAH!");
}

Se l'oggetto non può essere nullo (che appare corretto nell'esempio), è meglio farlo come segue:

Baz b = fooObject.foo(id);
if (b != null) {
   // do something with b
}
else {
   Error.screamAndRun("object lookup/whatever failed! AAaAAAH!");
}

Se l'oggetto può essere nullo, le eccezioni sono la strada da percorrere:

try {
   Baz b = fooObject.foo(id);
}
catch (BazException e) {
   Error.screamAndRun("object lookup/whatever failed! AAaAAAH!");
}

È uno schema comune utilizzato in C, dove non ci sono eccezioni. Permette alla funzione di restituire una condizione di errore. Le eccezioni sono generalmente una soluzione molto più pulita.

    
risposta data 13.05.2011 - 15:56
fonte

Leggi altre domande sui tag