Domanda

Se sto costruendo una stringa usando un oggetto StringBuilder in un metodo, avrebbe senso:

Restituisce l'oggetto StringBuilder e lascia che il codice chiamante chiami ToString ()?

return sb;

O Restituisce la stringa chiamando ToString () me stesso.

return sb.ToString();

Immagino che faccia la differenza se restituiamo stringhe piccole o grandi. Cosa sarebbe appropriato in ciascun caso? Grazie in anticipo.

Modifica: Non ho intenzione di modificare ulteriormente la stringa nel codice chiamante, ma buon punto Colin Burnett.

Principalmente, è più efficiente restituire l'oggetto StringBuilder o la stringa? Verrà restituito un riferimento alla stringa o una copia?

È stato utile?

Soluzione

Restituisce StringBuilder se intendi modificare ulteriormente la stringa, altrimenti restituisce la stringa. Questa è una domanda API.

Per quanto riguarda l'efficienza. Dal momento che questa è una domanda vaga / generale senza dettagli specifici, penso che mutevole o immutabile sia più importante della performance. La mutabilità è un problema API che consente alla tua API di restituire oggetti modificabili. La lunghezza della stringa è irrilevante per questo.

Detto questo. Se guardi StringBuilder.ToString con Reflector:

public override string ToString()
{
    string stringValue = this.m_StringValue;
    if (this.m_currentThread != Thread.InternalGetCurrentThread())
    {
        return string.InternalCopy(stringValue);
    }
    if ((2 * stringValue.Length) < stringValue.ArrayLength)
    {
        return string.InternalCopy(stringValue);
    }
    stringValue.ClearPostNullChar();
    this.m_currentThread = IntPtr.Zero;
    return stringValue;
}

Puoi vedere che potrebbe crearne una copia ma se lo modifichi con StringBuilder, ne farà una copia (questo è ciò che posso dire al punto di m_currentThread è perché Append controlla questo e lo copia se non corrisponde al thread corrente).

Immagino che la fine di questo sia che se non modifichi StringBuilder, non copi la stringa e la lunghezza è irrilevante per l'efficienza (a meno che tu non prema quel secondo se).

UPDATE

System.String è una classe che significa che è un tipo di riferimento (al contrario del tipo di valore), quindi "string foo; " è essenzialmente un puntatore. (Quando si passa una stringa in un metodo, passa il puntatore, non una copia.) System.String è mutabile all'interno di mscorlib ma immutabile al di fuori di esso, il che è il modo in cui StringBuilder può manipolare una stringa.

Quindi quando viene chiamato ToString () restituisce il suo oggetto stringa interno per riferimento. A questo punto non puoi modificarlo perché il tuo codice non è in mscorlib. Impostando il campo m_currentThread su zero, eventuali ulteriori operazioni su StringBuilder lo faranno copiare l'oggetto stringa in modo che possa essere modificato e non modificare l'oggetto stringa restituito in ToString (). Considera questo:

StringBuilder sb = new StringBuilder();
sb.Append("Hello ");

string foo = sb.ToString();

sb.Append("World");

string bar = sb.ToString();

Se StringBuilder non ne facesse una copia, alla fine foo sarebbe " Hello World " perché StringBuilder lo ha modificato. Ma dal momento che ne ha fatto una copia, Foo è ancora solo " Ciao " e la barra è " Hello World " ;.

Ciò chiarisce l'intera cosa di ritorno / riferimento?

Altri suggerimenti

Non credo che le prestazioni dovrebbero essere un fattore in questa domanda. In entrambi i casi qualcuno chiamerà sb.ToString () in modo da portare il colpo da qualche parte.

La domanda più importante è qual è l'intenzione del metodo e lo scopo. Se questo metodo fa parte di un builder, è possibile restituire il builder di stringhe. Altrimenti restituirei una stringa.

Se questo fa parte di un'API pubblica, mi spingerei a restituire una stringa anziché il builder.

Direi che il metodo dovrebbe restituire sb.ToString (). Se la logica che circonda la creazione dell'oggetto StringBuilder () dovrebbe cambiare in futuro, per me ha senso che sia cambiato nel metodo non in ogni scenario che chiama il metodo e poi continua a fare qualcos'altro

StringBuilder è un dettaglio di implementazione del tuo metodo. Dovresti restituire la stringa fino a quando non diventa un problema di prestazione, a quel punto dovresti esplorare un altro modello (come visitatore Pattern ) che può aiutarti a introdurre l'indirizzamento indiretto e a proteggerti dalle decisioni sull'implementazione interna.

Le stringhe vengono sempre memorizzate nell'heap, pertanto verrà restituito un riferimento se il tipo restituito è stringa. Non puoi contare, tuttavia, su due stringhe identiche per avere riferimenti identici. In generale, è sicuro pensare a una stringa come se fosse un tipo di valore anche se in realtà è un tipo di riferimento.

Penso che dipenda da cosa stai facendo con la stringa una volta che lascia il metodo. Se continuerai ad aggiungerlo, potresti prendere in considerazione l'idea di restituire un costruttore di stringhe per una maggiore efficienza. Se hai sempre intenzione di chiamare .ToString () su di esso, dovresti farlo all'interno del metodo per una migliore incapsulamento.

Restituirei una stringa in quasi tutte le situazioni, specialmente se il metodo fa parte di un'API pubblica.

Un'eccezione sarebbe se il tuo metodo è solo una parte di un più grande, privato "builder" processo e il codice chiamante eseguirà ulteriori manipolazioni. In tal caso, forse prenderei in considerazione la possibilità di restituire un StringBuilder .

Dal momento che non lo modificherai più

return sb.ToString();

dovrebbe essere più efficiente

Restituisce sb.ToString (). Il tuo metodo dovrebbe concentrarsi solo sulla cosa a portata di mano (in questo caso costruiscimi una stringa) e non essere restituito per essere ulteriormente manipolato dall'IMO, potresti entrare in tutti i tipi di problemi senza che venga eliminato.

Dipende da cosa stai pensando di fare con l'output. Vorrei restituire una stringa personalmente. In questo modo, se è necessario modificare il metodo lungo la strada per non utilizzare un costruttore di stringhe, è possibile poiché non rimarrete bloccati come valore di ritorno.

Pensandoci per il momento, la risposta è molto più chiara. La domanda su quale debba essere restituito risponde davvero alla domanda. L'oggetto return dovrebbe essere una stringa. Il motivo è che se stai ponendo la domanda, " C'è un motivo per restituire l'oggetto StringBuilder quando una stringa lo farà? & Quot; allora la risposta è no. Se ci fosse un motivo, restituire la stringa sarebbe fuori discussione, poiché sono necessari i metodi e le proprietà del stringbuilder.

Se è necessario aggiungere più elementi alla stringa e utilizzare altre funzionalità correlate a Stringbuilder, restituire Stringbuilder. Altrimenti se stai usando la stringa stessa, restituisci la stringa.

Ci sono altre considerazioni più tecniche, ma questo è il più alto livello di preoccupazioni.

Al metodo è stato assegnato un compito concreto e dovrebbe essere previsto di completarlo e restituire il risultato finito che non richiede ulteriori elaborazioni. Restituisci StringBuilder solo quando ne hai davvero bisogno. In tal caso aggiungi anche qualcosa al nome del metodo per indicare che stai restituendo qualcosa di speciale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top