Tabla de Contenido
0. Introducción1. Problema
2. Solución
3. Discusión de la Solución
4. Práctica: Código Fuente C#
4.1 Asignación de memoria de un objeto StringBuilder
4.2 Invertir cadena de caracteres
5. Conclusiones
6. Glosario
7. Enlaces & Literatura
0. Introducción
Bien
sabemos que el estado natural o la representación más primitiva de los datos corresponde con
cadenas de texto que pueden adquirir diferente significado según su contexto o representación:
numérico (útil para las operaciones aritméticas, e.g.), fecha (determinar la edad de una
persona por medio de la diferencia), texto (un párrafo de un libro), &c.
Los programadores lidian en su día a día de sus profesiones tratando con
cadenas de texto que deben ser tratadas de una u otra manera para alcanzar el
objetivo del sistema informático que esté construyendo. Hacer uso eficiente de
las construcciones del lenguaje es de importante cuidado, pues sabemos que hay
límites impuestos por la capacidad de cómputo del sistema en el que se
ejecutará la aplicación a desarrollar. En esta receta vamos a conocer un
recurso (tipo) del Framework .NET para manipular eficientemente cadenas de
texto. ¡Manos a la obra!
1. Problema
La manipulación de texto sobre tipos de datos string [3] puede crearnos problemas en el uso de la memoria stack (espacio de memoria para el almacenamiento de data de objetos) -cfr. Variables y Parámetros en C# - Parte 1-. Tenemos que atacar este problema de inmutabilidad de string [2] utilizando un tipo alternativo para hacer uso eficiente de la memoria.
2. Solución
El Framework .NET cuenta con una clase óptimamente diseñada para constuir cadenas de texto a través de manipulaciones programáticas (vía los métodos de su implementación). El nombre de clase completamente calificado (FQCN [4]):
System.Text.StringBuilder [2]
3. Discusión de la Solución
La clase string (alias de String) posee la misma característica de los tipos primitivos (o integrados), es decir los tipos numéricos: la de inmutabilidad. Se dice que una cadena de texto es inmutable porque su contenido (una vez creada) no puede ser modificado, en su lugar (e.g., cuando realizamos una concatenación de texto, como: "Hola" + "Mundo", estamos creando una nueva cadena a partir de las dos anteriores: "HolaMundo") se crea un nuevo tipo en la memoria stack de la CLR.
Veamos lo anterior con un ejemplo de código C# más completo:
// Primera cadena
// la variable nombreCompleto hace referencia al objeto con data "John"
String nombreCompleto = "John";
// Cuenta de objetos string en el stack: 1
// Proceso de concatenación
nombreCompleto = nombreCompleto + " Ortiz";
// Hasta este punto la variable nombreCompleto ahora apunta al objeto string
// con data "John Ortiz".
// Cuenta de objetos string en el stack: 2
La clase StringBuilder nos salva el día. Esta clase trabaja con un buffer de datos [4] que permite la manipulación de una cadena de texto; esto facilita y permite que en tiempo de ejecución se evite la creación de nuevos tipos string en la memoria stack: cada cada cambio sobre el contenido de la cadena mantendrá una única copia. Visto esto, ganamos eficiencia en el uso de los recursos de memoria y nuestra aplicación será más estable en ambientes de producción rígidos y exigentes.
Miremos cómo se compartaría (de forma análoga) el fragmento de código previo pero con StringBuilder:
// la variable nombreCompleto hace referencia al objeto StringBuilder con data "John"
System.Text.StringBuilder nombreCompleto = new System.Text.StringBuilder("John");
// Cuenta de objetos string en el stack: 1
// Proceso de 'adición' de cadeanas
nombreCompleto.Append(" Ortiz");
// El contenido de nombreCompleto: nombreCompleto.ToString() -> "John Ortiz"
// Cuenta de objetos string en el stack: 1
Algunas consideraciones importantes acerca del uso de objetos StringBuilder, en particular cuando adicionamos nuevos caracteres a la cadena:
- Capacity [6]: Esta propiedad corresponde con la capacidad del buffer (es decir, el número de caracteres) que puede contener un objeto StringBuilder en tiempo de ejecución). La capacidad inicial es de 16 caracteres. La capacidad se duplica cuando la CLR detecta la superación de la capacidad actual.
Desde [1] nos aconsejan tener cuidado con la manipulación de cadenas en este tipo de objetos, pues podríamos hacer que se pierdan las bondades al no manejar correctamente la capacidad a medida que añadimos bloques o caracteres individuales. - Length [7]: Corresponde con la cantidad de caracteres de la cadena localizada en el objeto StringBuilder.
Otras consideraciones adicionales a tener en cuenta:
- Al establecer la propiedad Capacity con una capacidad inferior a la de Length, la primera lanza la excepción: System.ArgumentOutOfRangeException.
La capacidad máxima de un objeto StringBuilder alcanza los 2 gigabytes. - Si establecemos un valor inferior a la longitud actual -propiedad Length- de la cadena en el objeto StringBuilder, entonces su contenido es truncado al nuevo valor inferior al actual.
- Al establecer un valor superior al de la propiedad Length, el buffer llena esos espacios vacíos con caracteres de espacio.
[Nota: Recomiendo ver el ejemplo enunciado en [8] para comprender la diferencia entre los tipos string y StringBuilder.]
4. Práctica: Código Fuente C#
Empecemos con esta sección práctica para comprender más interiormente esta clase tan útil para nuestros desarrollos donde la manipulación de cadenas de texto es un requisito ineludible.
4.1 Asignación de memoria de un objeto StringBuilder
Este primer ejemplo es una adaptación del hallado en [2].
Vamos a observar cómo un objeto StringBuiler localiza (asigna) memoria de forma dinámica: ampliando su capacidad según es necesario.
Archivo AsignacionMemoriaStringBuilder.cs:
En las líneas 26-36 se declara la función AsignacionMemoriaStringBuilder que permite conocer el estado actual de varias de las propiedades del objeto StringBuilder en tiempo de ejecución (usando Reflection -en futuro próximo hablaré más acerca de este tema-). Esta función es llamada cada vez que se adiciona texto a la instancia objSB (de tipo StringBuilder).
Compilación:
Ejecución:
Compilación:
- csc /target:exe /out:AsignacionMemoriaStringBuilder.exe AsignacionMemoriaStringBuilder.cs
Ejecución:
Figura 1. Ejecución del archivo AsignacionMemoriaStringBuilder.exe. |
4.2 Invertir Cadena de Caracteres
Con este ejemplo vamos a aprender cómo hacer uso eficiente de la manipulación de cadenas de caracteres a través de StringBuilder.
Archivo ManipulacionCadenas.cs:
En las líneas 24-44 se declara y se implementa el método InvertirCadena para invertir los letras de una cadena de caracteres. Observemos que esto ofrece una ventaja: el objeto StringBuilder que se crea en la línea 34 -cadenaInversa- empieza con una capacidad inicial equivalente a la longitud del objeto string -cadena-.
Compilación:
> Prueba de ejecución.
Compilación:
- csc /target:exe /out:ManipulacionCadenas.exe ManipulacionCadenas.cs
> Prueba de ejecución.
Conclusiones
Comprendimos con esta receta que la clase StringBuilder nos ofrece una composición lógica para la creación de cadenas de caracteres, pero sobretodo, la manipulación de cadenas de caracteres en tiempo de ejecución de forma más eficiente y natural.
Glosario
- Buffer
- Cadena de texto
- CLR
- Nombre completamente calificado
- Stack
Enlaces & Literatura
[1]:
Visual C# 2010 Recipes by Allen Jones and Adam Freeman. Copyright 2010 Allen
Jones and Adam Freeman, 978-1-4302-2525-6.
[2]:
StringBuilder Class (System.Text) - http://msdn.microsoft.com/en-us/library/system.text.stringbuilder%28v=vs.110%29.aspx
[3]: string (C# Reference) - http://msdn.microsoft.com/en-us/library/362314fe.aspx[4]: Data buffer - Wikipedia, the free encyclopedia - http://en.wikipedia.org/wiki/Data_buffer
[5]: StringBuilder.Capacity Property (System.Text) - http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.capacity%28v=vs.110%29.aspx
[6]: StringBuilder.Length Property (System.Text) - http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.length%28v=vs.110%29.aspx
[7]: ArgumentOutOfRangeException Class (System) - http://msdn.microsoft.com/en-us/library/system.argumentoutofrangeexception%28v=vs.110%29.aspx
[8]: The String and StringBuffer types - http://msdn.microsoft.com/en-us/library/system.text.stringbuilder(v=vs.110).aspx#StringAndSB
M
No hay comentarios:
Publicar un comentario
Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.