Pregunta

Si estoy creando una cadena usando un objeto StringBuilder en un método, ¿tendría sentido:

Devuelve el objeto StringBuilder y deja que el código de llamada llame a ToString ()?

return sb;

O Devuelve la cadena llamando a ToString () yo mismo.

return sb.ToString();

Supongo que marcará la diferencia si devolvemos cadenas pequeñas o grandes. ¿Qué sería apropiado en cada caso? Gracias de antemano.

Editar: No planeo modificar más la cadena en el código de llamada, pero bueno, Colin Burnett.

Principalmente, ¿es más eficiente devolver el objeto StringBuilder o la cadena? ¿Se devolvería una referencia a la cadena o una copia?

¿Fue útil?

Solución

Devuelva el StringBuilder si va a modificar aún más la cadena; de lo contrario, devuelva la cadena. Esta es una pregunta de API.

En cuanto a la eficiencia. Dado que esta es una pregunta vaga / general sin detalles específicos, entonces creo que mutable versus inmutable es más importante que el rendimiento. La mutabilidad es un problema de API al permitir que su API devuelva objetos modificables. La longitud de la cadena es irrelevante para esto.

Eso dicho. Si nos fijamos en 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;
}

Puede ver que puede hacer una copia, pero si la modifica con StringBuilder, hará una copia (esto es lo que puedo decir que el punto de m_currentThread es porque Append lo verifica y lo copiará si no coincide con el hilo actual).

Supongo que el final de esto es que si no modifica el StringBuilder, entonces no copia la cadena y la longitud es irrelevante para la eficiencia (a menos que presione ese segundo si).

UPDATE

System.String es una clase, lo que significa que es un tipo de referencia (en oposición al tipo de valor), por lo que " string foo; " Es esencialmente un puntero. (Cuando pasa una cadena a un método, pasa el puntero, no una copia). System.String es mutable dentro de mscorlib pero inmutable fuera de él, que es cómo StringBuilder puede manipular una cadena.

Entonces, cuando se llama a ToString (), devuelve su objeto de cadena interna por referencia. En este punto no puede modificarlo porque su código no está en mscorlib. Al establecer el campo m_currentThread en cero, cualquier otra operación en StringBuilder hará que copie el objeto de cadena para que pueda modificarse y y no modifique el objeto de cadena que devolvió en ToString (). Considera esto:

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

string foo = sb.ToString();

sb.Append("World");

string bar = sb.ToString();

Si StringBuilder no hizo una copia, entonces al final foo sería '' Hello World '' porque StringBuilder lo modificó. Pero dado que hizo una copia, foo sigue siendo solo "Hola". y la barra es "Hola Mundo".

¿Eso aclara todo el asunto de devolución / referencia?

Otros consejos

No creo que el rendimiento deba ser un factor en esta pregunta. De cualquier manera, alguien va a llamar a sb.ToString () para que lleves el golpe a algún lugar.

La pregunta más importante es cuál es la intención del método y el propósito. Si este método es parte de un generador, puede devolver el generador de cadenas. De lo contrario, devolvería una cadena.

Si esto es parte de una API pública, me inclinaría por devolver una cadena en lugar del generador.

Diría que el método debería devolver sb.ToString (). Si la lógica que rodea la creación del objeto StringBuilder () debe cambiar en el futuro, tiene sentido para mí que se cambie en el método, no en cada escenario que llama al método y luego pasa a hacer otra cosa

StringBuilder es un detalle de implementación de su método. Debe devolver la cadena hasta que se convierta en un problema de rendimiento, momento en el que debe explorar otro patrón (como visitante Patrón ) que puede ayudarlo a introducir indirección y protegerlo de las decisiones de implementación internas.

Las cadenas siempre se almacenan en el montón, por lo que tendrá una referencia devuelta si el tipo de retorno es cadena. Sin embargo, no puede contar con dos cadenas idénticas para tener referencias idénticas. En general, es seguro pensar en una cadena como si fuera un tipo de valor, aunque en realidad sea un tipo de referencia.

Creo que depende de lo que esté haciendo con la cadena una vez que abandona el método. Si va a continuar añadiéndole, entonces puede considerar devolver un generador de cadenas para una mayor eficiencia. Si siempre va a llamar a .ToString (), debe hacerlo dentro del método para una mejor encapsulación.

Devolvería una cadena en casi todas las situaciones, especialmente si el método es parte de una API pública.

Una excepción sería si su método es solo una parte de un constructor privado más grande '' proceso y el código de llamada hará más manipulaciones. En ese caso, podría considerar devolver un StringBuilder .

Ya que no lo vas a modificar más

return sb.ToString();

debería ser más eficiente

Devuelve el sb.ToString (). Su método debe concentrarse solo en lo que tiene a mano (en este caso, construirme una cadena) y no ser devuelto para ser manipulado más IMO, podría tener todo tipo de problemas si no se elimina.

Depende de lo que esté planeando hacer con la salida. Yo devolvería una cadena personalmente. De esa manera, si necesita cambiar el método en el futuro para no usar un generador de cadenas, puede hacerlo, ya que no se quedará con eso como valor de retorno.

Al pensarlo por el momento, la respuesta es mucho más clara. La cuestión de preguntar cuál debería devolverse realmente responde a la pregunta. El objeto devuelto debe ser una cadena. La razón es que si está haciendo la pregunta, "¿Hay alguna razón para devolver el objeto StringBuilder cuando lo hará una cadena?" Entonces la respuesta es no. Si hubiera una razón, entonces devolver la cadena estaría fuera de discusión, porque se necesitan los métodos y propiedades del generador de cadenas.

Si necesita agregar más cosas a la cadena y usar otras funciones relacionadas con el generador de cadenas, devuelva el generador de cadenas. De lo contrario, si solo está utilizando la cadena, devuelva la cadena.

Hay otras consideraciones más técnicas, pero esas son las preocupaciones de más alto nivel.

El método recibió una tarea concreta y se espera que lo complete y devuelva el resultado final que no requiere procesamiento adicional. Solo devuelve StringBuilder cuando realmente lo necesite. En ese caso, también agregue algo al nombre del método para indicar que está devolviendo algo especial.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top