Como implementar correctamente IDisposable…

Primero lo primero… La interface IDisposable define un método “personalizado” para liberar los recursos administrados y no administrados.
IDisposable se usa principalmente para liberar los recursos no administrados, ya que el recolector de elementos no utilizados (GC: Garbage Collector) libera automáticamente la memoria asignada a un objeto administrado cuando ya no se utiliza, pero no se puede prever cuándo se producirá la recolección de elementos no utilizados. Además, el GC no reconoce recursos no administrados, como ser objetos de tipos File y Font.

A continuación, les muestro el código de ejemplo y aclaraciones sobre la implementación de una clase IDisposable:

public class ClaseDisposable : IDisposable {
    // Recursos manejados
    private Component componentes = new Component();
    private DataSet dataSetDisposable = new DataSet();

    // Indica si ya se llamo al método Dispose. (default = false)
    private Boolean disposed;

    /// <summary>
    /// Implementación de IDisposable. No se sobreescribe.
    /// </summary>
    public void Dispose() {
        this.Dispose(true);
        // GC.SupressFinalize quita de la cola de finalización al objeto.
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// Limpia los recursos manejados y no manejados.
    /// </summary>
    /// <param name="disposing">
    /// Si es true, el método es llamado directamente o indirectamente
    /// desde el código del usuario.
    /// Si es false, el método es llamado por el finalizador
    /// y sólo los recursos no manejados son finalizados.
    /// </param>
    protected virtual void Dispose(bool disposing) {
        // Preguntamos si Dispose ya fue llamado.
        if (!this.disposed) {
            if (disposing) {
                // Llamamos al Dispose de todos los RECURSOS MANEJADOS.
                this.componentes.Dispose();
                this.dataSetDisposable.Dispose();
            }

            // Acá finalizamos correctamente los RECURSOS NO MANEJADOS
            // ...

        }
        this.disposed = true;
    }

    /// <summary>
    /// Destructor de la instancia
    /// </summary>
    ~ClaseDisposable() {
        this.Dispose(false);
    }
}

Podemos agregar que el método Dispose(bool disposing) es virtual, por lo que podemos redefinirlo en clases que hereden de esta, por lo cual en dichas clases no necesitamos implementar nuevamente IDisposable. Un ejemplo de este comportamiento es un Formulario que hereda (obviamente) de Form, como vemos a continuación, en Designer tenemos el siguiente código:

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) {
     if (disposing && (components != null)) {
          components.Dispose();
     }
     base.Dispose(disposing);
}

También podemos ver como sería la llamada a Dispose. Hay dos tipos de llamadas, la directa y la indirecta:
Llamada Directa:

ClaseDisposable objetoDisposable = new ClaseDisposable();
// utilizamos el objetoDisposable
// ...
// y lo finalizamos:
objetoDisposable.Dispose();

Llamada Indirecta:

using (ClaseDisposable objetoDisposable = new ClaseDisposable()) {
    // utilizamos el objetoDisposable
    // ...
}
//se finaliza automáticamente al salir del using

Más información sobre using…

Espero que les sea útil.
(FxCop nos sugiere la implementación de IDisposable de esta manera cuando nuestra clase trabaja con recursos administrados y que implementan el método Dispose… Es bueno hacerle caso, implementando IDisposable como corresponde 😀 )

Anuncios
Publicado en C#, Tips. Etiquetas: . Leave a Comment »

Operador as…

Les presento el operador as, es un operador de conversión bastante conocido, pero tiene características muy útiles que son interesantes de recalcar.

El operador as se utiliza para realizar conversiones entre tipos de referencia compatibles.

Veamos:

String cadena = objetoCadena as String;

sería (pero no lo es del todo) equivalente a:

String cadena = (String)algunObjeto;

Pero… ¿cuál es la verdadera diferencia?.
El operador as es similar a una operación de conversión de tipos; sin embargo, si la conversión no es posible, as devuelve null en lugar de producir una excepción.

Formalmente podemos decir que el operador realiza lo siguiente:

expresion is tipo ? (type)expresion : (type)null;

entonces lo utilizamos de la siguiente forma:

String cadena = objetoCadena as String;
if (cadena != null) {
    //objetoCadena ES un String.
}
else {
    //objetoCadena NO ES un String.
}

que es equivalente (y más performante) a:

if (objetoCadena is String) {
    //objetoCadena ES un string.
    String cadena = (String)objetoCadena;
}

NOTA: digo que as es más performante que el último ejemplo porque al realizar “objetoCadena is String” se realiza un casteo interno, siendo que después nosotros nuevamente lo realizamos dentro del if.
(FxCop notifica con un issue que realicemos este cambio de implementación)

Publicado en C#, Tips. Etiquetas: . 2 Comments »

StringBuilder…

Ante la necesidad de manipular cadenas de caracteres dinámicamente nos encontramos con dos posibilidades:

  1. manejar cadenas con la clase String y realizar sobre él acciones como ser concatenación, reemplazo, inserción, etc.
  2. manejar cadenas con la clase StringBuilder.

Lo más común y más “fácil” es trabajar con String, mantener una instancia e ir realizando tratamientos sobre ella, como ser concatenar strings por medio del operador +,  lo cual nos lleva a crear código poco performante y hasta por momentos engorrosos. Dado que los Strings son de tamaño fijo, al concatenar dos cadenas con el operador + se crea una instancia aparte, lo que  lleva a disminuir el rendimiento debido al mal uso de memoria.

Por lo tanto para operar con cadenas de caracteres lo más formal (y también más óptimo) es utilizar la clase StringBuilder.

¿Qué podemos hacer con  StringBuilder?

La clase StringBuilder nos provee los siguientes métodos:

  • Append: Anexa al final de la instancia la representación en forma de cadena de un objeto especificado.
  • AppendFormat: Anexa a la instancia una cadena con formato, que contiene cero o más especificaciones de formato. Cada especificación de formato se reemplaza por la representación en forma de cadena de un argumento de objeto correspondiente.
  • AppendLine: Anexa el terminador de línea predeterminado, o una copia de una cadena especificada y el terminador de línea predeterminado, al final de esta instancia.
  • CopyTo: Copia los caracteres de un segmento especificado de esta instancia al segmento especificado de una matriz Char de destino.
  • EnsureCapacity: Garantiza que la capacidad de la instancia de StringBuilder corresponde como mínimo al valor especificado.
  • Remove: Elimina de la instancia el intervalo de caracteres especificado.
  • Replace: Reemplaza todas las apariciones de un carácter o cadena en la instancia por otro carácter o cadena especificados.
  • ToString: Sobrecargado. Reemplazado. Convierte el valor de un objeto StringBuilder en un objeto String.

Ejemplo:

usando String:

String mensaje = "Medios de pago excedidos de saldo: ";
foreach (DocSaldo.SaldoRow fila in doc.Saldo.Rows) {
    mensaje += Environment.NewLine + fila.MedioPago;
}

usando String Builder:

StringBuilder mensaje = new StringBuilder("Medios de pago excedidos de saldo:");
mensaje.Append(Environment.NewLine);

foreach (DocSaldo.SaldoRow fila in doc.Saldo.Rows) {
    mensaje.AppendLine(fila.MedioPago);
}
String mensajeString = mensaje.ToString();

Como se puede notar, la segunda opción es más formal y me atrevo a decir “más Orientada a Objetos”.

Una observación adicional es el constructor del StringBuilder, el cual en una de sus sobrecargas nos permite inicializarlo con una cadena de caracteres.

Cuando implementamos la primera opción FxCop nos indica con un issue que debemos cambiarlo por el uso de StringBuilder, que es la segunda opción.

Más información:

http://msdn.microsoft.com/es-es/library/system.text.stringbuilder(VS.80).aspx

Publicado en C#, Tips. Etiquetas: . 2 Comments »

Shortcuts de Microsoft Visual Studio .Net…

Les dejo un link a una página que encontré hace un tiempo, la misma contiene los shortcuts que posee el VS.

http://www.codinghorror.com/blog/files/Visual%20Studio%20.NET%202005%20Keyboard%20Shortcuts.htm

De más está comentar las ventajas de conocer los atajos.

Nombro algunos pocos atajos que me parecieron útiles:

  • DataSet:
    • ctrl + l: para agregar una nueva columna. Especialmente útil cuando tenemos una granmn cantidad de columnas a agregar.
  • Globales:
    • ctrl + shift + f: abre la búsqueda en archivos. Esta búsqueda es la que yo más utilizo, debido a que busca a gran velocidad ya sea en el documento, en el proyecto e incluso en la solución.
    • F4: muestra la ventana de propiedades.
    • F12: “Go to definitions”. Va a la definición del método, propiedad o atributo sobre el que estamos situados.
    • F5: compilar y comenzar a Debuguear. (ctrl + F5: comenzar a Debuguear sin compilar)
    • F6: compilar la solución. (shift + F6: compilar el proyecto actual).
    • F7: estando situados en “Solution explorer”, en una clase en particular o control, presionando esta tecla entramos a ver el código del mismo.
    • F9: Agregar/quitar breakpoint.
    • ctrl + b, t: Agregar/quitar un bookmark sobre la línea en la que estamos situados.
    • ctrl + m, ctrl + o: Colapsa todas las definiciones.
    • ctrl + m, ctrl + m: Colapsa la definición sobre la línea en la que estamos situados.

Algunos tips de VS.NET y C# [Parte 1]

IDE a pantalla completa:
Si queremos un mayor espacio para nuestro IDE presionando shift + alt + enter podemos hacer que tome la pantalla completa.
Pegar texto almacenados en el portapapeles:
Visual Studio mantiene el texto copiado y cortado en un portapapeles. Si usamos ctrl + v se pega el último texto copiado, pero si mantenemos presionado ctrl + shift y presionamos v una y otra vez se nos aparecen los textos que estan almacenados en el portapapeles.
Búsqueda incremental:
Se puede realizar una búsqueda incremental si presionamos ctrl + i, luego comenzamos a escribir el texto que buscamos y si queremos salir de la búsqueda sólo necesitamos presionar esc. Si el cursor está en un resultado, para saltar al próximo solo debemos presionar ctrl + i nuevamente. Para saltar al resultado anterior debemos presionar ctrl + shift + i.
Auto-completar:
Mientras estamos escribiendo código VS y su intellisense nos ayuda a auto-completar el nombre de la palabra que estamos escribiendo si presionamos ctrl + barra espaciadora o alt+flecha derecha. Si existe más de una concordancia nos arrojará el listado con las posibilidades (este es el listado al que se puede acceder presionando ctrl + j.
Organización de soluciones:
Si la solución sobre la que se trabaja tiene una gran cantidad de proyectos o simplemente por el hecho de organizar las distintas capas, es recomendable utilizar lo que se denomina “Solution Folders”. Estas son carpetas que nos ayudan a agrupar proyectos con características en común. Estas carpetas se agregan haciendo click derecho en la solución-> Add->New Solution Folder. Una implementación sería crear una carpeta para cada capa Acceso a datos, Negocio y Presentación. Generar solution folders es una práctica muy muy común y muy utilizada en todos los proyectos. Por ejemplo la solución donde trabajo tiene 110 proyectos, si todos ellos colgaran de la Solución, sería prácticamente imposible encontrar un proyecto en particular. Por esto y muchas cosas más yo le digo “Gracias Solution Folders!!!”.
Mostrar excepciones donde ocurren:
Si queremos que se muestre (o no) en modo Debug las excepciones donde ocurren, más allá de si hay un try{}catch{} que lo capture, hay que ir a Debug -> Exceptions (ctrl + D, E) y checkear o descheckear la opción Common Language Runtime Exceptions en la columna Thrown.
Operador ?? (no muy conocido):
El operador ?? se aplica sobre variables “nullables”, permitiendo una menor escritura de código y se aplica del siguiente modo :
Int32? x;

Int32 i = x ?? 0;

el código mencionado lo que hace es, si la variable a la izquierda del operador ?? es nulo devuelve la variable de la derecha, en el caso de que la variable de la izquierda no sea nulo devuelve dicha variable.
Esto también puede aplicarse a por ejemplo:
String texto = null;

String salida = salida ?? “No especificado”;

Esta es la primer parte de los tips que he ido recolectando, próximamente habrá mas posteos, pero si quieren compartir alguno haganlo como comentarios! Serán bienvenidos.