RSS 2.0 Atom 1.0 CDF  
JASoft.org - Programación
El blog de José Manuel Alarcón Aguín. Programación .NET y mucho más...
 

Esta pregunta surgió el otro día en uno de mis cursos on-line de campusMVP y la verdad es que es bastante interesante, no tanto porque sea especialmente difícil de hacer, si no por las implicaciones que tiene su aplicación en la práctica.

La idea está muy bien: dado que estoy almacenando objetos de mi programa en disco (o enviándolos a través de la red), si los comprimo debería ahorrar espacio en disco y/o ancho de banda. De hecho, la idea es tan buena que en ASP.NET 4.0 una de las novedades es que el almacenamiento de sesión fuera de proceso (es decir, cuando guardamos la sesión en un servidor de estado remoto o en un SQL Server), tiene una nueva opción para permitir la compresión de los datos antes de enviarlos para su almacenamiento o recuperación de sesión. Esto es muy útil para sitios web que quieren acelerar la transferencia de información en una granja de servidores, pero tiene la contrapartida de que los procesadores estarán más cargados debido a las operacioens de compresión y descompresión.

Antes de entrar en detalles sobre si esto es realmente tan bueno como parece, vamos a ver cómo podríamos implementarlo de manera sencilla con nuestro propio código.

El código de seriación (es la palabra adecuada en español, frente al más comñun "serialización" que es una adaptación del término anglosajón) sería este:

public static void SeriaYComprime(object obj, string arch) { 
	using(FileStream fs = new FileStream(arch, FileMode.OpenOrCreate, FileAccess.Write)) {
		using (GZipStream zs = new GZipStream(fs, CompressionMode.Compress, true)) { 
			BinaryFormatter bf = new BinaryFormatter(); 
			bf.Serialize(zs, obj);
		} 
	}
}

A este método se le pasa el objeto que queremos seriar y una ruta en disco para almacenarlo y seria el objeto para almacenarlo en formato binario, usando un BinaryStream y un GZipStream por debajo para conseguir la compresión. Muy sencillo.

Por supuesto, en lugar de almacenar a disco podríamos almacenar a memoria con un MemoryStream o a cualquier otra ubicación, pero el código sería prácticamente igual.

El código para conseguir la deseriación sería como este:

public static object DescomprimeYDeseria(string arch) { 
	using (FileStream fs = new FileStream(arch, FileMode.Open, FileAccess.Read)) {
		using (GZipStream zs = new GZipStream(fs, CompressionMode.Decompress, true)) { 
			BinaryFormatter bf = new BinaryFormatter();
			return bf.Deserialize(zs); 
		}
	} 
} 

Que es el proceso inverso al que hicimos antes, es decir, se indica el archivo, y éste se lee usando un formateador binario que usa a su vez un GZipStream por debajo en modo descompresión.

Si ahora tenemos una clase "serializable" cualquiera, por ejemplo esta:

[Serializable]
public class PruebaClaseSeriable
{
	public string Propiedad1 {get; set;}
	public int Propiedad2 {get; set;}
	public long Propiedad3 {get; set;}
}

y escribimos esto:

PruebaClaseSeriable pcs = new PruebaClaseSeriable();
pcs.Propiedad1 = "Hola";
pcs.Propiedad2 = 2;
pcs.Propiedad3 = 3;

SeriaYComprime(pcs, @"D:\PruebaCompr.bin");

Obtendremos un archivo "pruebaCompr.bin" en la raíz de la unidad D: con el estado completo del objeto. Este archivo lo podemos usar cuando queramos para recrear de nuevo el objeto en memoria simplemente llamando al otro método complementario:

PruebaClaseSeriable pcs2 = (PruebaClaseSeriable) DescomprimeYDeseria(@"D:\PruebaCompr.bin");

Listo. Tendríamos el objeto pcs2 con un estado idéntico al que teníamos anteriormente, aunque se reconstruya días más tarde o en una máquina diferente (esa es la idea de la seriación, o como dicen los modernos que trabajan con SOA, la idea de la deshidratación/hidratación).

En este archivo ZIP (3,56 KB) puedes descargarte el código de ejemplo e incluye también una versión sin compresión de los métodos de seriación/deseriación de objetos.

El efecto conseguido puede ser el contrario

Todo esto está genial y funciona a las mil maravillas. Sin embargo seriemos el mismo objeto anterior con y sin compresión y examinemos más de cerca los dos archivos generados.

El que no lleva compresión ocupa 229 bytes, y el que está comprimido pesa ¡294 bytes!
WTF? ¿Cómo es posible? ¡El comprimido ocupa más!.

En efecto, esto es así ya que la compresión no viene sola sino que trae una serie de elementos previos, en forma de cabecera de archivo, para poder hacer posteriormente la descompresión. Y estos elementos de la cabecera ocupan un cierto espacio (algo más de 100 bytes). Por lo tanto en este caso la compresión obtenida es mínima y encima tenemos la cabecera, por lo que al final acabamos con un archivo mucho mayor :-(

Probemos a sustituir el lacónico "Hola" de la Propiedad1 del objeto por los cuatros primeros párrafos de "El Quijote", que son 5.046 caracteres (está incluido en el ejemplo descargable anterior).
Ahora el seriado sin compresión ocupa 5.400 bytes y el comprimido 2.968 byes, es decir, ahora sí que hemos ganado mucho. En concreto el comprimido ocupa sólo el 55% de lo que ocupaba el que no lleva compresión. No está mal.

Conclusión

La compresión a la hora de seriar objetos para transportarlos o almacenarlos puede estar bien si dichos objetos contienen muchos datos, pero en objetos pequeños con pocos miembros y poca información será contraproducente. Además en ambos casos tendremos una mayor demanda del procesador por lo que si esto es importante para nosotros debemos tenerlo en cuenta. Puede ser muy útil la compresión para seriar objetos grandes y, sobre todo colecciones o matrices de múltiples objetos pequeños, que será más comun.

Espero que el tema te haya resultado interesante y le puedas sacar partido en la práctica.

Por: José Manuel Alarcon | Sunday, May 30, 2010 8:05:48 PM (Hora de verano romance, UTC+02:00)  #    Comments [2] - Trackback
Tags: ASP.NET | Programación



Sígueme en:

:: Twitter JM Alarcón: tecnología, marketing, este blog y frikadas varias
:: Twitter campusMVP: los mejores recursos sobre tecnología Microsoft: trucos, artículos, noticias, vídeos...
:: Facebook campusMVP: los mismos mejores recursos pero en directamente en Facebook.
:: Boletín campusMVP Nuestra publicación electrónica, una vez al mes en tu buzón de correo.
 
Banner

De este tema ya había hablado en una ocasión en este blog (o más bien en su blog gemelo), y lo cierto es que levantó bastante polémica.

Cuando hablo con alguna gente acerca de las novedades de Visual Studio 2010 y sale lo de las mejoras para la programación en paralelo, mucha gente lo ve como una mera anécdota, algo que no va con ellos en absoluto. Si bien es cierto que muchas aplicaciones que se hacen, como las de gestión por ejemplo, no suelen tener que sacarle partido, no es menos cierto que en muchas circunstancias nuestras aplicaciones deben poder sacarle el máximo rendimiento al hardware del que disponemos.

Desde hace unos años lo más habitual en cualquier ordenador corriente es que disponga de un procesador con al menos dos núcleos. En servidores o máquinas destinadas a tareas más demandantes es muy frecuente que haya varios procesadores con al menos cuatro núcleos. La tendencia es que cada vez haya más núcleos en los procesadores, ya no sólo por rendimiento sino por las ventajas en cuanto a ahorro de energía, temperatura y las limitaciones existentes en cuanto a aumentar la velocidad de frecuencia de reloj. Esto implica que casi cualquier aplicación pueda trabajar en entornos con múltiples núcleos, lo que hace realmente importante sacarle partido a la programación multi-subproceso.

Anteriormente, y aquí viene lo importante, para aumentar el rendimiento de una aplicación bastaba con moverla a una máquina con un procesador más rápido. Sin embargo hoy en día esto ya no vale, pues el rendimiento se obtiene a través de sacarle partido a más núcleos y no aumentando la velocidad. Así que la conclusión es que si queremos que una aplicación llegue a ser escalable ésta debe sacar partido a múltiples hilos de ejecución y, por lo tanto, a múltiples nodos de procesamiento.

¿Se ve entonces la importancia? A mi me parece fundamental.

Este tipo de programación paralela siempre ha sido muy compleja, sobre todo a la hora de depurar aplicaciones en las que existen muchas probabilidades de generar interbloqueos o “race conditions”. Con .NET 4.0 y Visual Studio 2010 se incluyen nuevas bibliotecas, tipos y herramientas para facilitar la programación multi-núcleo, y debería ser un área de suma importancia para los programadores.

.NET 4.0 incluye lo que se ha bautizado como “Parallel Extensions” que están formadas por tres nuevos componentes:

La biblioteca de tareas paralelas (TPL, Task Parallel Library): esta biblioteca dentro del espacio de nombres System.Threading.Taks.Parallel incluye construcciones para ejecutar tareas repetitivas independientes entre sí en paralelo y de forma automática, como por ejemplo versiones paralelas de los bucles For y ForEach.
El motor de ejecución paralela de Linq (PLINQ Execution Engine): como se desprende de su nombre, se trata de una versión paralelizada de Linq to Objects, que nos permite lanzar consultas integradas en el lenguaje aprovechando la capacidad de paralelismo del sistema.
Las estructuras de datos para coordinación (CDS, Coordination data Structures): ofrece un conjunto de primitivas de sincronización y de colecciones preparadas para multisubproceso (thread-safe) que simplifican los escenarios paralelizados. Por ejemplo, tenemos diccionarios, pilas y colas thread-safe, y objetos especiales para sincronización de hilos como el SpinWait o el SpinLock.

La MSDN tiene una buena documentación sobre todo esto en: http://msdn.microsoft.com/en-us/library/dd460693.aspx.

Y tú ¿qué opinas?

Por: José Manuel Alarcon | Sunday, May 09, 2010 9:26:53 PM (Hora de verano romance, UTC+02:00)  #    Comments [0] - Trackback
Tags: Programación | Visual Studio



Sígueme en:

:: Twitter JM Alarcón: tecnología, marketing, este blog y frikadas varias
:: Twitter campusMVP: los mejores recursos sobre tecnología Microsoft: trucos, artículos, noticias, vídeos...
:: Facebook campusMVP: los mismos mejores recursos pero en directamente en Facebook.
:: Boletín campusMVP Nuestra publicación electrónica, una vez al mes en tu buzón de correo.
 
Banner

<DISCLAIMER>Han pasado unos cuantos días desde que he podido postear algo nuevo. Me ha pillado de lleno el famoso volcán islandés que ha paralizado el tráfico aéreo en Europa, por lo que he estado atrapado varios días en Bruselas sin posibilidad de salir de allí y, lo que es peor, ¡sin ordenador ni Internet! :-S </DISCLAIMER>

Esta es una pregunta muy habitual que he visto por ahí y que realmente es muy sencilla de poner en marcha:

"¿Cómo puedo llamar a una página Web (o recurso remoto HTTP) desde mi propio programa y mostrar el resultado en mi aplicación?"

La respuesta es muy sencilla, pero no todo el mundo sabe cómo hacerlo. Básicamente hay que utilizar la clase WebRequest. Este método, por ejemplo, sirve para solicitar un determinado recurso a partir de su URL, que se le pasa como parámetro, devolviendo una cadena con el contenido del recurso (o generando una excepción si el recurso no existe o da un error):

	static string LeerRecursoWeb(string laUrl)
	{
		// Cear la solicitud de la URL.
		WebRequest request = WebRequest.Create(laUrl);
		// Obtener la respuesta.
		WebResponse response = request.GetResponse();
		// Abrir el stream de la respuesta recibida.
		StreamReader reader = new StreamReader(response.GetResponseStream());
		// Leer el contenido.
		string res = reader.ReadToEnd();

		// Cerrar los streams abiertos.
		reader.Close();
		response.Close();
		
		// Devolver resultado
		return res;
	}

Cómo vemos es bastante directo. Ahora, por ejemplo, podemos mostrar los enlaces más relevantes sobre ASP.NET en Delicious usando el siguiente código (en este caso para una aplicación de consola, pero valdría para cualquier otra):

		Console.WriteLine(LeerRecursoWeb("http://feeds.delicious.com/v2/RSS/popular/ASP.NET"));

Muy sencillo.

Los detalles importantes

Hay algunos detalles que merece la pena comentar.

La clase WebRequest es abstracta. Esto quiere decir que no se usa directamente, sino que se utiliza para crear otras clases derivadas que implementan los métodos apropiados según el protocolo a utilizar. Por ello existen en la plataforma .NET otras clases más especializadas como HttpWebRequest, FtpWebRequest o FileWebRerquest, especializadas en llamar a recursos por HTTP, por FTP y por el sistema de archivos respectivamente.

El método Create de la clase abstracta, en función de la URL que le pasemos, crea la clase derivada adecuada para gestionar el protocolo que se deba utilizar y obntener así el resultado. Gracias a ello, la función que pongo más arriba funcionaría también con las siguiente URLs:

		Console.WriteLine(LeerRecursoWeb("ftp://ftp.miservidor.com/carpeta/miarchivo.txt"));
		Console.WriteLine(LeerRecursoWeb("file://c:\MiCarpeta\Miarchivo.txt"));

De este modo el código se adapta a la URL usando la clase más apropiada en cada caso, lo que nos da mucha flexibilidad.

Por supuesto si quisiésemos restringir el uso a un protocolo concreto, como solamente el HTTP, es posible usar de manera directa cada una de estas clases especializadas y el código sería igual.

También existen otras clases especializadas, como por ejemplo WebClient, que nos permiten más control y enviar datos además de recibirlos, pero para responder a la pregunta planteada y poder empezar a investigar un poco por tu cuenta tienes material más que de sobra :-)

NOTA: Por cierto, hay que incluir los espacios de nombres System.IO y System.Net, no te olvides...

Por: José Manuel Alarcon | Thursday, April 22, 2010 7:34:29 PM (Hora de verano romance, UTC+02:00)  #    Comments [0] - Trackback
Tags: Programación



Sígueme en:

:: Twitter JM Alarcón: tecnología, marketing, este blog y frikadas varias
:: Twitter campusMVP: los mejores recursos sobre tecnología Microsoft: trucos, artículos, noticias, vídeos...
:: Facebook campusMVP: los mismos mejores recursos pero en directamente en Facebook.
:: Boletín campusMVP Nuestra publicación electrónica, una vez al mes en tu buzón de correo.
 
Banner

Las interfaces en .NET y otros lenguajes son una manera de establecer un contrato entre dos clases, de manera que dejemos perfectamente definido de qué manera vana poder interactuar entre ellas. Así, si una clase implementa una determinada interfaz sabemos que dicha clase va a disponer de determinados métodos y podemos contar con ellos a la hora de trabajar con ésta. Además gracias a las interfaces podemos implementar ciertos tipos de polimorfismo o genericidad a la hora de trabajar con conjuntos de clases que implementan la misma interfaz.

En fin, nada nuevo en el párrafo anterior para un programador mínimamente experimentado de .NET o cualquier otro lenguaje orientado a objetos. En nuestro curso de preparación del examen 70-536 se trata profusamente este tema, como es lógico. Lo interesante, y objeto de este post, viene a la hora de decidir cómo implementar una determinada interfaz en una clase. Así, si tenemos definida una interfaz cualquiera, por ejemplo esta:

public interface IMiInterfaz
{
	void MiMetodo();
}

Tenemos dos formas de implementarla en una clase. La primera de ellas es la manera implícita:

public class PruebaInterfazImplicita : IMiInterfaz
{
	public void MiMetodo()
	{
		Console.WriteLine("Hola");
	}
}

La otra manera es la explícita, en la que indicamos de manera evidente qué interfaz estamos implementando:

public class PruebaInterfazExplicita : IMiInterfaz
{
	void IMiInterfaz.MiMetodo()
	{
		Console.WriteLine("Hola");
	}
}

Fíjate que en este caso ponemos el nombre de la interfaz delante del método para indicar a qué interfaz pertenece éste, y además el método no es público.

Generalmente los programadores no le damos importancia a la forma en la que se implementa una interfaz y se usan indistintamente ambas formas, pero ¿realmente existe alguna diferencia?

Pues sí, hay diferencias y son importantes. A continuación resumiré los detalles relacionados con la implementación de interfaces y con qué cosas debemos tener cuidado.

1.- Implementación de varias interfaces

En .NET no existe la herencia múltiple de clases. Algunos alegarán que es una carencia, y otros dirán que es incluso una ventaja. Se ha escrito mucho sobre el tema. Lo que sí está permitido es la implementación de diversas interfaces. Así, si tenemos dos interfaces que definen métodos con el mismo nombre ¿cómo distinguimos unos de otros?. Por ejemplo, si tenemos dos interfaces I1 e I2 así:

public interface I1
{
	void M();
}

public interface I2
{
	void M();
}

public class PruebaDobleInterfaz : I1, I2
{
	public void M()
	{
		Console.WriteLine("Método M");
	}
}


public class Prueba
{
	public static void Main()
	{
		PruebaDobleInterfaz obj = new PruebaDobleInterfaz();
		obj.M();
		((I1) obj).M();
		((I2) obj).M();
		Console.Write("Pulsa una tecla para terminar...");
		Console.ReadKey();
	}
}

¿Cual será el resultado del código anterior? Pues que funcionará perfectamente y obtendremos el mismo texto tres veces, resultado de llamar al método M. Esto está genial si realmente queremos que la implementación del método sea idéntica en ambos casos, pero al tratarse de interfaces diferentes generalmente no será así. Ahí es donde entra la implementación explícita, ya que indicaremos qué interfaz exactamente estamos implementando y no habrá confusión posible. Si ahora definimos la clase así:

public class PruebaDobleInterfaz : I1, I2
{
	public void M()
	{
		Console.WriteLine("Método M");
	}
	
	void I1.M()
	{
		Console.WriteLine("Método I1.M");
	}
	
	void I2.M()
	{
		Console.WriteLine("Método I2.M");
	}
}

Pues ahora el código anterior mostrará tres mensajes diferentes, dependiendo de si llamamos al método M en la clase, o en una interfaz específica.

2.- Ocultar la implementación de miembros de interfaces

Al implementar de manera explícita miembros de interfaces lo que conseguimos es ocultarlos frente a su uso directo en la clase. Por ejemplo:

public interface IMiInterfaz
{
	void MiMetodo();
}

public class PruebaInterfazImplicita : IMiInterfaz
{
	void IMiInterfaz.MiMetodo()
	{
		Console.WriteLine("Hola");
	}
}

public class Prueba
{
	public static void Main()
	{
		PruebaInterfazImplicita obj = new PruebaInterfazImplicita();
		//obj.MiMetodo(); //Produce un error de compilación de que la clase no contiene ese método
		((IMiInterfaz) obj).MiMetodo();
		Console.Write("Pulsa una tecla para terminar...");
		Console.ReadKey();
	}
}

Fíjate que ahora la llamada al método implementado explícitamente falla cuando lo intentamos hace directamente desde la clase, y se requiere el "casting" explícito a la interfaz para poder llamarlo. Además el método nose mostrará a los programadores en el Intellisense de Visual Studio, por lo que n tendrán la tentación de usarlo de cualquier manera, ocultándolo efectivamente.

¿Para qué podría servir esto? Pues por ejemplo para ocultar ciertos miembros que queremos que se usen con cuidado y sabiendo lo que se hace. Por ejemplo, es muy típico hacer esto al utilizar la interfaz IDisposable, ocultando la implementación del método Dispose() que debe ser llamado por el runtime y no generalmente por el programador.

3.- Ni públicos, ni virtuales ni abstractos

Los métodos de interfaces implementados de manera explícita no pueden definirse como públicos (se declaran automáticamente como privados para ocultarlos) ni tampoco como abstractos o virtuales. Hay que tenerlo en cuenta por si lo necesitásemos. Esto tiene dos importantes implicaciones:

1.- las clases que implementan interfaces de manera explicita no pueden ser abstractas.
2.- Las clases derivadas de clases que implementan interfaces de manera explícita no pueden sobrescribir los métodos definidos explícitamente.

Detalles adicionales

Si quieres ver algunos ejemplso más de cómo implementar interfaces explícitamente puedes echarle un vistazo a este documento de MSDN (en español): Tutorial de implementación explícita de interfaces.

Si ya dominas el tema y quieres profundizar para conocer los detalles de bajo nivel de cómo se implementan por debajo ambas formas de declarar métodos de interfaces, te recomiento este excelente artículo sobre el asunto de Chris Brumme, ingeniero distinguido de Microsoft, aquí: "cbrumme's Weblog: Interface Layout". ¡Realmente interesante!

Espero que te haya resultado interesante, aunque sea algo árido :-)

Por: José Manuel Alarcon | Wednesday, March 31, 2010 4:47:00 PM (Hora de verano romance, UTC+02:00)  #    Comments [0] - Trackback
Tags: Programación



Sígueme en:

:: Twitter JM Alarcón: tecnología, marketing, este blog y frikadas varias
:: Twitter campusMVP: los mejores recursos sobre tecnología Microsoft: trucos, artículos, noticias, vídeos...
:: Facebook campusMVP: los mismos mejores recursos pero en directamente en Facebook.
:: Boletín campusMVP Nuestra publicación electrónica, una vez al mes en tu buzón de correo.
 
Banner

Algunas preguntas que recibo con frecuencia en el curso de preparación del examen 70-536 en campusMVP están relacionadas con las estructuras y las clases en .NET. Esta misma semana he tenido un par de ellas muy interesantes, lo que me lo ha recordado y me he decidido a resumir aquí algunas de estas preguntas y sus respuestas.

¿Cuál es la principal diferencia entre una estructura y una clase?

La principal diferencia entre Estructura y Clase es que las primeras son tipos por valor y las otras tipos por referencia. Es decir, aunque los primeros pueden trabajar como clases, realmente son valores ubicados en la pila directamente, y no punteros (referencias) a la estructura en memoria. Esto significa que los primeros se pueden gestionar más eficientemente al instanciarlos (se hace más rápido), sobre todo en grandes cantidades, como una matriz. Al crear una matriz de estructuras éstas se crean consecutivamente en memoria y no es necesario instanciar una a una y guardar sus referencias en la matriz, por lo que es mucho más rápido su uso. Por el contrario si pasas a un método una estructura, al hacerlo se crea una copia de la misma en lugar de pasar una referencia y por lo tanto los cambios aplicados sobre ella se pierden. El rendimiento es menor también.

Lo mismo pasa al aplicar ciertas funciones de objetos a estructuras en las que hay que hacer Boxing y Unboxing y eso merma el rendimiento.

¿Cuándo es interesante usar una estructura en lugar de una clase?

Lo habitual es no usar estructuras casi nunca, salvo para realizar optimizaciones.

Un caso concreto de uso de una estructura sería si, por ejemplo, quieres trabajar con números complejos, que como seguramente sabrás están representados por dos cifras: una parte real y una imaginaria. Si quieres tratarlos como un número más, es decir, que sean un tipo por valor, lo lógico es que los hagas estructuras para no tener que instanciarlos y para que cuando llames a métodos pasándole números complejos éstos se pasen por valor, y no se modifiquen con lo que hagas dentro del método al que los pasas. A todos los efectos se comportarían como si fueran otro tipo por valor, como un entero o un double.

Otro ejemplo, más común, es cuando debes trabajar con una cantidad muy elevada de objetos en memoria, uno tras otro. Por ejemplo imagínate que tienes que hacer una transformación sobre puntos tridimensionales en el espacio. Te puedes crear una clase que los represente, pero si debes ir creando y procesando miles de ellos será mucho más eficiente crearlos usando estucturas porque de este modo se crean en la pila y se libera su espacio en cuanto dejas de necesitarlos (los objetos quedarían en memoria hasta la próxima vez que los necesites). 

También hay escenarios de interoperabilidad, cuando se llama a código nativo usando PInvoke, o a objetos COM usando COM/Interop, donde es necesario pasar estructuras y no clases. Pero vamos, como resumen quedate con que, salvo casos raros, todo debe ser clases.

¿Qué diferencia hay entre usar o no New al declarar una variable cuyo tipo es una estructura?

Consideremos por ejemplo esta estructura en C#:

public struct Punto 
{
    public int x, y;
}

O en VB:

Public Structure Punto
    Public X, Y As Integer
End Structure

Puedes declarar una variable que las use de dos formas diferentes: usando New o no. Por ejemplo en VB:

Dim p As Punto
Dim p As New Punto

¿Cuál es la diferencia? A priori parece no haber ninguna. Sin embargo sí que la hay, y tiene que ver con extender las estructuras con propiedades y métodos. 

Las estructuras se pueden extender con métodos, propiedades, etc.. como si fueran clases. Por ejemplo, consideremos el siguiente código en C#:

public struct Punto
{
	int x, y;
	
	public int X
	{ 
		get { return x; }
		set { x = value; }
	}

	public int Y
	{ 
		get { return y; }
		set { y = value; }
	}
}

Si escribimos el siguiente código (el más habitual):

Punto p;
Console.WriteLine (p.x);

obtendremos un error que nos dice que la variable interna 'x' no está inicializada. Sin embargo con este otro código:

Punto p = new Punto();
Console.WriteLine (p.x);

No se produciría error alguno.

Lo importante aquí es que, al ser declaradas por defecto (sin constructor), las estructuras no inicializan sus miembros internos, por lo tanto antes de usarlos debemos asignarles un valor. Cada propiedad tiene un campo interno que no está inicializado cuando intentamos usarlo a través de la propiedad, y obtendrías un error al hacerlo (no se sabe si tu propiedad antes de asignarlo intenta hacer algo con él y por lo tanto te obliga a tenerlo inicializado). Si usas el constructor por defecto explícitamente (con la palabra clave new) lo que éste hace es inicializar todos los miembros internos a su valor por defecto, y a partir de ese momento ya te deja utilizarlos. Si no usas new no se llama al constructor por defecto y los campos están sin inicializar.

Otros posts

Los siguientes siguientes posts de este blog están relacionados también con, que explican precisamente algunas diferencias importantes entre clases y estructuras en determinadas situaciones:

- Diferencias al usar Clases y Estructuras en matrices
- Algunas sutilezas sobre paso de parámetros por referencia y por valor en C#
- Nada se crea ni se destruye, sólo se transforma... Excepto las cadenas en .NET

¡Espero que te resulte útil!

Por: José Manuel Alarcon | Friday, March 26, 2010 2:55:50 PM (Hora estándar romance, UTC+01:00)  #    Comments [0] - Trackback
Tags: Programación



Sígueme en:

:: Twitter JM Alarcón: tecnología, marketing, este blog y frikadas varias
:: Twitter campusMVP: los mejores recursos sobre tecnología Microsoft: trucos, artículos, noticias, vídeos...
:: Facebook campusMVP: los mismos mejores recursos pero en directamente en Facebook.
:: Boletín campusMVP Nuestra publicación electrónica, una vez al mes en tu buzón de correo.
 
Banner
Page 1 of 41 in the Programación category Next Page
Copyright © 2010 José Manuel Alarcón Aguín. All rights reserved.