Nada

domingo, 18 de mayo de 2008

Funciones con parámetros variables

La idea es tener una función que puede llamarse con cero, uno o varios parámetros, por ejemplo:

funcion(parametro1);

funcion(parametro1, parametro2);

funcion(parametro1, parametro2, parametro3);

En C# disponemos una forma de trabajar con un conjunto variable de parámetros, usando un concepto que se llama "arreglo variable de parámetros".

Para que una función pueda recibir un conjunto variable de parámetros, la declaramos usando el modificador params, de esta forma:


void funcion(params object[] p)
{
// definición de la función ...
}

Hay que destacar que el tipo de los parámetros puede ser cualquiera, no necesariamente object.

Cuando hacemos uso una función definida con parámetros variables, podemos conocer el número de parámetros recibidos mediante la propiedad Count de p:


void funcion(params object[] p)
{
// definición de la función
if (p.Count() == 0) return;
}



Nota para los programadores de Pivotal


La implementación de la clase de PivotalObject que abstrae el diccionario de lenguajes (y que por lo general tiene el nombre LangDict) está hecha usando el concepto de arreglo variable de parámetros. Cada LDString se convierte en un método que recibe un arreglo variable de parámetros, por ejemplo:


public class MiDiccionarioLangDict
{
public string MiLDString(params string[] p)
{
// Implementación de la función
}
}

jueves, 1 de mayo de 2008

Tipos por Valor vs. Tipos por Referencia

En Visual C# existen dos tipos de variables, y para el desarrollador de aplicaciones es muy importante saberlo, y saber cómo y cuando está usando un tipo u otro, porque de ello depende en buena medida la calidad de su desarrollo.

Las variables pueden ser por Valor o por Referencia.

Un Tipo por Valor es un tipo que contiene los propios datos almacenados. Podemos imaginarnos los Tipos por valor como una cajita donde metemos cosas. Cuando necesitamos usar la cosa, vemos el contenido de la cajita, y lo manipulamos directamente. Los tipos numéricos de Visual Studio: int, long, double, float son ejemplos de Tipos por Valor.

Cuando asignamos a una variable de un tipo por valor el contenido de otra variable, hacemos una copia de la "cosa" contenida en la cajita, y desde ese momento, ambas copias son completamente independientes. Pongamos un ejemplo:


static void Main(string[] args)
{
int i;
int j;

i = 1;
j = i;
i++;
j--;
Console.WriteLine(String.Format("i={0} j={1}", i, j));

// i=2 j=0, porque al asignar j=i, lo que hacemos es
// una copia de su contenido.

Console.ReadKey();
}


Los Tipos por Referencia, por el contrario, son tipos que contienen una referencia a los datos, en vez de los datos en si. Podemos imaginarnos los tipos por referencia como una cajita donde, en vez de cosas, guardamos un papel que dice donde está la cosa que queremos usar.

Cuando asignamos una variable de un tipo por referencia a otra, copiamos el papel que dice dónde está guardada la cosa. Algunos ejemplos de tipos por referencia son object, List, etc.


static void Main(string[] args)
{
List L;
List M;

L = new List();
L.Add(7);

M = L;
M.Add(1);

Console.WriteLine(String.Format(
"Elementos en L={0} Elementos en M={1}", L.Count, M.Count));

// Elementos en L=2 Elementos en M=2, porque L y M apuntan al
// mismo objeto.

Console.ReadKey();
}




El caso del tipo string es particular, ya que es un tipo por referencia, pero se comporta como un tipo por valor. Esto se debe a que Visual Studio .Net define los strings como inmutables, es decir: una vez creado el objeto, no se puede cambiar de ninguna manera.

Notas para quienes programan Pivotal CRM


El objeto Recordsets que se manipula en varios de los Puntos de Transición del sistema es, naturalmente, un tipo por referencia; y su contenido (los recordsets que representan los datos del Primario y cada uno de los Secundarios del Form) también lo son.

Como consecuencia de eso, podemos perfectamente manipular cualquiera de esos recordsets mediante variables de tipo Recordset, y no es necesario volver a asignar estas variables al objeto Recordsets:



Recordset rst;

rst = (Recordset) Recordsets[0];
rst.Fields[strfNOMBRE_CAMPO].Value = "Valor";

// NO es necesario hacer lo siguiente:
// Recordsets[0] = rst;


domingo, 9 de marzo de 2008

Clases divididas en partes

En algunos de mis proyectos, tengo clases que contienen unas dos mil líneas de código. Hasta ahora, la única forma que teníamos para organizar el código de una clase así de grande, era definir regiones. En Visual Studio 2003 el manejo de las regiones no funciona correctamente del todo, por ejemplo, al hacer búsquedas de texto se omiten las regiones colapsadas. En VS 2008 podemos implementar el código de una clase en varios archivos, declarándola "partial". Por ejemplo:

Fichero 1

partial class Class1
{
public void method1() { }
}

Fichero 2


partial class Class1
{
public void method2() { }
}

Al compilar, la clase resultante luce más o menos así (observen que los dos métodos aparecen como miembros de la clase):



Esta es una forma interesante de dividir el código de un proyecto muy grande sin tener que alterar la estructura modular del mismo. Por ejemplo, podríamos asignar cada archivo a un desarrollador distinto para que puedan trabajar simultáneamente, incluso, si estamos trabajando vajo Visual Source Safe u otro sistema de control de versiones.

viernes, 7 de marzo de 2008

El sutra del programador

Programador, el usuario es tu enemigo.

Debes saciar su hambre y aplacar su ira, que tu programa lo sacie y lo calme, pero ¡cuidado! él tratará paciente e inexorablemente de quebrar tu código: tocará botones que no debe y cuando no debe, meterá datos incorrectos, por torpeza y por pura maldad, cerrará la ventana activa a mitad del proceso, apagará el computador mientras tu programa corre y pulsará el botón de reset con los dedos de la mano y los de los pies.

Por lo tanto, que tu programa sea no sólo para saciar el hambre y aplacar la ira de tu usuario. ¡Defíendete de él! Tapa todos los huecos, cúbrete las espaldas y asegúrate que hay al menos un handler para cada evento, por inesperado que sea.

domingo, 24 de febrero de 2008

Propiedades Automáticas en C#2008

C# 2008 incorpora varias mejoras del lenguaje. Por lo que he visto, ninguna es tan radical ni tan últil como los genéricos introducidos en C# 2005, pero algunas sí que son interesantes.

La posibilidad de definir Propiedades Automáticas es una, al menos, interesante, por no decir curiosa. Se trata de la posibilidad de dejarle al compilador la tarea de generar el código para manejar la asignación (set) y la recuperación (get) de un campo privado asociado a la propiedad.

Me explico con un ejemplo. En C# 2005 teníamos que declarar una propiedad más o menos así:

class x
{
protected int _myprop;
public int myprop
{
get {return _myprop;}
set {_myprop = value;}
}
}

Esto puede quedar reducido a una sola línea:

class x
{
public int myprop {get; set;}
}


Yo, la verdad, no tengo muy clara la utilidad de esta construcción en C#. La idea de usar propiedades es ofrecer cierto nivel de abstracción mediante ocultamiento de los miembros de la clase que no son parte de la interfaz, y tiene mucho sentido cuando una propiedad afecta el comportamiento de otras, pero en el contexto, la única diferencia es que el miembro se expondría como property y no como variable.

Las propiedades automáticas están sumamente limitadas: no se tiene acceso al miembro privado subyacente, y además es requerido implementar toda la propiedad como automática (no se puede implementar el set automático y el get por código, o viceversa).