lunes, 27 de abril de 2015

La evolución de la música y el entretenimiento como servicio

La siguiente entrada es un extracto de un texto perteneciente a una actividad calificable del master “Investigación en Ingeniera del Software” que me encuentro actualmente cursando, exactamente para la asignatura “Arquitecturas Orientadas a Servicio”.

En este extracto hablo de la evolución de lo música y el entretenimiento audiovisual desde hace 30 años a la actualidad, para analizar cómo esta evoluciono desde un modelo basado en el producto físico a un modelo de distribución basado en servicios.


En los años 80 y principios de los 90 eran común ver el uso de Walkman, reproductores de casetes de música, de relativo pequeño tamaño, que se podría sostener una mano, aunque de manera no muy cómoda. Estos reproductores nos permitían llevar nuestra música favorita con nosotros mismos, pero de una forma limitada, en cada casete se podría almacenar desde 30 a 120 minutos (en los últimos modelos), y cada casete ocupada un volumen que no permitía trasportar más de dos o tres de una forma sencilla.


Aunque de una manera un tanto tosca (desde un punto de vista actual), el consumo de música se desplazaba desde el hogar, a cualquier parte, integrándose como parte de nuestra actividades cotidianas. La música comenzaba a convertirse de cierta manera en un servicio, al poder ser consumida desde cualquier parte. Pero un servicio limitado, puesto que si bien, la "música" nos acompañaba donde quisiéramos, la cantidad de esta música que pudiéramos consumir el dispositivo era muy limitada, y distaba mucho de ser "En demanda".

Adicionalmente era común que los aficionados hicieran recopilaciones de sus canciones favoritas en un solo casete, lo cual llego a llamarse "Mixtape" (desechando las canciones que no le gustaban), con lo que de esta primitiva forma, se da dos elementos fundamentales, definitorios de servicios:

  • La movilidades del servicio (el servicio va donde va el usuario).
  • La selección del los contenidos por parte del usuario (El usuario decide que servicios quiere y cuáles no).






En los 90 se hizo popular otro formato de audio, el compact disc, abreviado como CD, era un soporte óptico que podía almacenar aproximadamente 90 minutos de audio, a la vez que era multipropósito pudieron almacenar 700 megas de información.

Este nuevo formato era más sencillo de transportar y almacenar, y su calidad de sonido era superior y no se degradaba con el número de reproducciones, con lo que acabo sustituyendo completamente al viejo formato de casete. Para este formato también surgieron reproductores de audio portátiles, como el discman, que realizan las mismas funciones que el walkman, pero además, unas nuevas, como por ejemplo, una pantalla (display) donde mostrar información de las canciones, tal como el numero de canción o su duración, posibilidad de saltos, prácticamente instantáneos, entre canciones, y reproducción aleatoria de estas. De esta forma, aun todavía, de forma limitada, el usuario podía ir al contenido que quería de una forma más directa y clara. El punto negativo de estos dispositivos fue la duración de su batería.




Parablemente a esto, y en la misma década, se popularizaron el uso de la computación domestica, en que era común, tener un ordenador en la casa, para diversas tareas, y para finales de los 90, que esta estuviera conectada a internet. Igualmente en la misma época se popularizo el uso de los archivos compartidos de audio, los cuales podrían almacenar una canción, en unas 15 veces menos espacio (de disco) que lo que se podría hacer con un formato sin comprimir. De esta manera se podía tener almacenado en un disco duro, una canción de forma individual, siendo esta completamente digital y con la ventaja que se podría añadir información adicional, como el nombre del artista, el del álbum o el de la fecha de publicación, Siendo el formato más popular el MP3 MPEG-2 Audio Layer III,

La popularización de internet y los archivos MP3, llevo a que los usuarios quisieran compartir tus experiencias multimedia entre sí. A raíz de eso se alzo Napster en 1999, como sistema de intercambio de archivos entre distintos usuarios, sin necesidad de un servidor (constituyendo redes de pares o P2P). Por este programa (y otros), los usuarios compartían su música y obtenían su vez música de otros usuarios, aunque la forma de hacerlo esta dentro una marco "alegal", según desde donde según se mirada y por quien. El caso es que resulto sumamente extendida y habría un nuevo "gusto" de los usuarios en cuanto al consumo de sus servicios, "Obtener lo que quisiera, de forma sencilla y si necesidad de desplazarse de su casa", así si el usuario quería escuchar una canción tanto antigua como nueva, simplemente lo buscaba en su computadora, y lo escuchaba directamente.





Aunque las discográficas se oponían a esta forma de distribución de música (debido a que no les reportaban ningún beneficio directo), los fabricantes de dispositivos vieron una posibilidad en la creación de aparatos de reproducción portátiles de MP3. Por lo menos, si no pudieran vender música, venderían hardware. Estos aparatos llegaron a ser mucho más pequeños y cómodos de manejar en diversas circunstancias (como correr), que los tradicionales walkman o discman, además permitían almacenar un número más elevado de canciones, de forma que no era necesario llevar consigo casetes o disco adicionales. En esta forma se simplifico el uso y la facilidad de trasporte de la "música", aun más, el formato en el que se guardaba la música dejo de ser transcendente, pasando a tener en cuenta la música en si como el servicio, y no el soporte físico en sí.



La desventaja de estos primeros reproductores MP3, es que no estaban pensados para promover el consumo (redistribuible) de la música en sí, solo para aprovechar la creciente distribución de archivos MP3, (su venta no suponía vender más música, sino simplemente aumentar los consumidores de MP3). Compañías como Sony, se veían en medio de este enfoque, por un lado era una discográfica (Sony Music), y por otro un fabricante de diversos dispositivos, incluyendo los reproductores de audio, sin poder progresar correctamente en un sector (la venta de música) o en otro (la venta de reproductores), a pesar que sus dos facciones podrían haber colaborado para marcar un camino a seguir en este aspecto.

La venta de CD tuvo su auge en el año 2000, y desde entonces ha ido en descenso, aumentando a su vez el uso de música en fichero digitales, como el mencionado MP3, ocurriendo una batalla entre las discográficas y los nuevos formatos junto a los creadores de fabricantes de programas de intercambio de música. Concluyendo con una demanda y el cierre de Napster, y la creación de programas alternativos, con semejantes funciones (como Ares o eMule). Aparente imparables, los programas de intercambio, fueron sustituyendo a la venta de disco, a la par que las grandes discográficas no sabían qué hacer para adaptarse a este potencial mercado, insistiendo en continuar con un modelo de ventas y distribución que claramente se estaba quedando obsoleto.

Al margen de estos cambios en la industria (pero sin duda relacionados ellos) en la segunda mitad de los 90, se producía el retorno de Steve Jobs a Apple, la cual hacia algún tiempo en que había perdido su rumbo, su identidad y su posición en el mercado. Que en esa época estaba controlado prácticamente por Microsoft y sus sistemas. Jobs a regresar a Apple, elimino muchos productos que no aportaban el beneficio requerido a la empresa (como las impresoras), reduciendo lo que hacía Apple a un rango de productos pequeño (exactamente cuatro, uno cada sector, domestico, profesional, portátil y de escritorio), pero con alta prestaciones y sencillos de manejar, a la vez que establecía nuevas relaciones empresariales, como con Microsoft, y finalizaba otras, como con Adobe.

Unos de los principales objetivos de Jobs para Apple, es simplificar el uso de sus sistemas , y crear productos atractivos para el público en general, en ese sentido (entre otros), se creó el iMac, el puerto firewire, el reproductor (software) Itunes, y finalmente el iPod, en el año 2001.

El iPod era un dispositivo reproductor multimedia, con un gran diseño y grandes capacidades de almacenamiento (como mil canciones), pero sobretodo una gran sencillez de uso. El dispositivo carecía casi de botones, su funcionalidad consistía en el uso de una simple "rueda" que da acceso a todas las canciones. De esta forma se elimina la multitud de botones, interruptores y led que poseían los otros reproductores, y que hacían complicado y inaccesible su uso. Con lo que hacia este dispositivo hacia que se cumpliera otro de los requisitos del uso de servicios que es la "sencillez de uso".





Apple tenía en su momento, toda una gama de productos controlado por en su totalidad por ellos, un iMac, como centro de software, un puerto de alta velocidad de transferencia "Firewire", un organizador de archivos multimedia el iTunes, y un reproductor portátil de audio de altas prestaciones el iPod. El único factor que no controlaba, y por el cual no obtenía un beneficio directo, era la música en sí. Eso cambio con el nacimiento de iTunes Store, en el 2003, una tienda virtual, en la que los usuario podrían comprar y obtener música de forma legal, y sencilla. Se podía comprar música desde la comodidad el hogar, a través de la computadora y sincronizarlos con nuestro dispositivo iPod, Además y representando un cambio en la manera de pensar de las discográficas, es posible comprar las canciones de forma individual, sin necesidad de comprar un álbum completo. se comprendió por fin que es más sencillo que un cliente compre una canción que le guste primero y se decida a comprar el álbum completo o divisos álbumes, que compre en primera instancia un disco, si solo le gusta una canción pudiéndola obtenerla por otros mecanismos o programas de intercambio, gratis en internet.

La idea fue un éxito, y se inicio un nuevo modelo de distribución, que generaba dinero, cómodo tanto para las distribuidoras, como para los clientes, que levanto nuevamente el negocio discográfico, desde una nueva perspectiva.

En este punto tenemos todos los elementos indispensables para convertir la música en un servicio como tal, con las siguientes características.

  • La música se puede obtener bajo demanda, en cualquier momento, y desde la comodidad el hogar, en este caso bajo un pequeño costo, además de poder encontrar el contenido que exactamente nos interesa (como las canciones individuales).
  • La música en transportable fácilmente y se puede acceder a ella en cualquier momento (aunque no se puede acceder, todavía, a cualquier canción desea, si no se cargo previamente).
  • Es sencillo de usar y consumir por casi cualquier persona.






Posteriormente con la llegada de teléfonos inteligentes, como iPhone en el 2007, y posteriormente otros basado en Android en fechas posteriores, se abrió un mundo de posibilidades en cuanto a servicios, incluido la música como servicio. Entre otras cosas, se creó la posibilidad de estar siempre conectado a internet (de forma inalámbrica o por redes de telefónica), y consumir instantáneamente y donde fuera los mencionados servicios (con mayor o menor éxito según la infraestructura de comunicaciones móviles de cada país).

Con la llegara de dichos teléfonos, surgieron nuevos sistema de distribución de música, como Spotify (en el 2009 de forma mundial), que permitan escuchar música, donde fuera y sin necesidad de una precarga de esta en el móvil. Con dos modelos de distribución, uno basado en publicidad (gratuito para el usuario), y otro en una tarifa plana, en la que por una cantidad mensual (de aproximadamente 9 dólares), en la que el usuario puede escuchar la música que quiera, las veces que guste, mientras su suscripción este activa.

Con esto se cumple otro requisito de los servicios, y es obtener lo que se necesita (en este caso música), donde se requiera. Es se podría obtener cualquier canción (que ofrezca el servicio), en el móvil, el cualquier momento y en cualquier lugar (donde se tengan acceso a internet).





Google Play Music, es la tienda de música de Google, lanzada en el año 2011. Dicha tienda tiene factores en común con iTunes, al permitir compra de música individualmente (y almacenamiento de esta en la nube), y tener un servicio de suscripción como Spotify, de tarifa plana para escuchar la música desea en cualquier momento. Este servicio esta forma nativa en los teléfonos Android.

Este servicio en particular tiene una característica especial, está integrado con el resto de servicios de Google, al cual se acceder con una misma cuenta (generalmente un email de gmail). A través de dicha cuenta se realiza un seguimiento de actividades que realizamos en otros servicios de Google, por ejemplo podemos buscar un video músical en YouTube, Google recordara dicha búsqueda y nos la ofrecerá como opción musical en Google Play Music, es mas, ofrecerá música que guarda relación con la ya hemos escuchado, sugiriéndonos nuevas canciones a través de lo que él piensa que es nuestro gusto musical. Dejando al lado temas relacionados con la privacidad, que puede ser todo un tema a parte, cuando mas usemos los servicios proporcionados por Google, incluido correo electrónico, búsquedas en YouTube o compra en Google Play, o historial previo de reproducciones (puede que incluso de otros usuarios), mas nos conocerá y con mas certeza ofrecerá servicios (o música en este caso), mas relacionados con nuestros gustos e inquietudes.

Es este punto tenemos una nueva característica relacionadas con los servicios, y es la personalización (automática) de estos, hacia nuestras necesidades y gustos particulares, se podría decir que los servicios “nos entienden”.

Semejante al desarrollo de la música como el servicio se dio la migración de formatos audiovisuales, como películas y series, a su distribución como servicios.

Los orígenes del consumo domestico masivo de los contenidos audiovisuales comenzaron con el VHS, formato completamente analógico, el cual estaba en pleno auge en los 80 (en competencia con el Betamax). El VHS, se hizo común que a finales de los 80 y durante los años 90, y en la primera parte de los años 00, la creación de videoclubs, donde la gente podría alquilar películas durante uno o dos días, sin necesidad de comprarlas y por pequeño precio. Era una versión muy primitiva del entretenimiento orientado a servicios (en el proveedor del servicio era el videoclub).

El VHS, tenía sus ventajas y sus desventajas, como que era muy grande y difícil de transportar, además que se degradaba con el tiempo (con cada reproducción al ser un soporte magnético).



El VHS dio paso al DVD en el año 1995, pasando por varios formatos sin mucha relevancia (comercial) como el VCD, o el Laser-disc. El DVD, era disco compacto con una gran capacidad de almacenamiento, y gran calidad de imagen y sonido, a la vez que podría incluir extras, como escenas descartadas, o subtítulos y audio en varios idiomas. Finalmente de forma progresiva en al año 2000 el DVD sustituyo definitivamente al VHS.

Una de las grandes ventajas de este formato, es que era muy barato de generar, además de ser fácilmente trasportable y almacenable, con lo que era normal que periódicos lo ofrecieran de forma gratuita y editoriales sacaran ediciones que se vendían incluso en los kioscos, sacando ediciones de películas antiguas, extranjeras (de poca difusión), o series de televisión (que no era común verlas editadas en VHS), esto contribuyo a que el consumo de contenidos audiovisuales se extendiera de forma masiva, con lo que tenemos otros de los factores relevantes a los servicios, la accesibilidad.

El formato DVD, en la actualidad está dejando paso a Blu-Ray (desde el años 2006), aunque todavía se está implementando de forma domestica, debido al costo actual de los discos, para el usuario final, y a que debe competir con las copias digitales. Actualmente es normal encontrar que se distribuyen de forma conjunta, Blu-Ray, DVD y contenido digital, con la intención de conseguir una migración de reproductores DVD a Blu-Ray,y abarcar el uso de posibles copias digitales.






El aumento de la velocidad de descarga que ofrecieron los proveedores de internet, desde finales de los 90 hasta que la actualidad, ha hecho que se popularicen el intercambio de archivos multimedia, al igual que las canciones, la gente compartían videos y series de televisión de la misma forma que antes estaban compartiendo música, programas como eMule o eDonkey2000, o uTorrent sustituyeron y ampliaron la funcionalidad de Napster.

El mismo problema surgido con las discográficas, surgió con las distribuidas de películas. Afectados por las distribuciones de contenidos a través de internet, que no les reportaban beneficios, grande cadenas de videoclubs, como Blockbuster Video, se declararon en bancarrota en el año 2010.

Sin embargo surgieron otras cadenas que se adaptaron al cambio digital y a nuevas formas de distribución, entre ellas Netflix, que permita, de forma semejante a Spotify en su sector, ofrecer una tarifa plana para visualizar series y películas sin límites (mientras durada la suscripción). No solo eso sino que era posible visualizar el contenido en ordenadores, pero también en tablets, teléfonos móviles, o de una manera más tradicional en televisiones inteligentes (muchas de las cuales vienen con la aplicación de Netflix instalada por defecto). Netflix ha tenido un crecimiento tan importante que incluso en los últimos años ha decidió crear sus propias series y contenidos (además de proporcionar contenidos creados por los distribuidores clásicos). En este momento y al igual que la música, las series, documentales y películas, son accesibles como servicios, en el formato, en el dispositivo y el momento en que sean requeridos por los usuarios.





En este capítulo hemos visto como la música y la televisión han evolucionado desde ser productos físicos que se ofrecen como tal, a auténticos servicios consumidos a petición de clientes, que son más demandantes en cuanto a el momento y la forma en lo que los quieren consumir.

martes, 7 de abril de 2015

Gestión de memoria en sistemas .NET

La siguiente entrada es un extracto de un texto perteneciente a una actividad calificable del master “Investigación en Ingeniera del Software” que me encuentro actualmente cursando, exactamente para la asignatura “Desarrollo de software Seguro”.

En este extracto hablo de manera breve de la gestión de memoria de .NET, así como de su recolector de basura, comparándolos a C, y mostrando diferencias y semejanzas entre ambos lenguajes de programación.

Gestión de memoria en sistema .NET

Tradicionalmente C/C++, tiene ciertas características con respecto al uso y gestión de la memoria, que si no son tenidas en cuenta podrían generar diversos problemas en nuestra aplicación. La mayoría de estos problemas tienen que ver con los punteros, y resumiéndolos podrían quedar en la siguiente lista:
  • El programador es responsable de obtener los recursos necesarios y libéralos. con lo que se puede "olvidar" de liberarlos apropiadamente.

  • Lo array no validan "fronteras". podemos sáltanos libremente dichas fronteras (tamaño máximo o mínimo), y el sistema posiblemente no generar ningún fallo, hasta que se genere un error desconocido e inesperado en un punto del sistema que nos será difícil diagnosticar y puede exponer una vulnerabilidad.

  • Los objetos pueden hacerse cast libremente entre ellos, sin comprobar que el tipo destino sea adecuado con respecto al origen, lo cual pueden generar liersos resultado inesperados.
  • El tamaño de la variables numéricas podría varias con respecto a las arquitectura (x64 y x86), lo que podría revelar vulnerabilidades con respecto a la interconexión entre varios sistema, o con la compilación en una nueva arquitectura.
  • Muchas funciones devuelve un código de error numérico para validar el éxito de la función pero debido a que no interrumpen la ejecución del programa, si ese valor no es comprobado siempre, el sistema continuara ejecutándose con un valor inconsistente.
  • Todas la validaciones que tiene que usar el programador, colección de clases seguras que sustituyen a otras inseguras (que siguen existiendo y existiendo en las universidades), así como versiones especial de las funciones para trabajar con encodings de texto diferente. hace que C o C++ sea particularmente difíciles de entender para un programador novato.

Tanto Java, como posteriormente C#, hicieron especial énfasis, en solucionar todos los problemas o dificultades relativos al uso de memoria (entre otras temas relacionados con C++, como simplicidad de los mecanismo de herencia, y la sintaxis).

Se podría decir que en C#, casi todo es un puntero, salvo que no se llama como tal siendo el nombre más apropiado que se le da "referencia". Las variables se separan en tipos por "valor", que son principalmente las estructuras y números básicos (como enteros), y se guardan en la pila de memoria y tipos por referencia (el resto de los objetos), que se guarda en el montículo de la memoria.

Las variables se pasan, por defecto, por valor a las funciones (esto quiere decir que se pasa una copia de la variable), esto genera confusión al pensar que cuando pasamos un objeto entre funciones se copiara el objeto. Este no es el comportamiento real, lo que se pasa es una copia a la referencia al objeto, con lo que si cambiamos algo del mismo objeto estaremos cambiando realmente el objeto original, pero si le asignamos a la variable otro valor, realmente estamos asignando a esa variable una referencia a un objeto completamente nuevo que se perderá una vez finalizada la variable. Para conservar el valor, se puede agregar el prefijo ref (que indica que se debe conservar el valor de la variable si se asigna a otro objeto), o el prefijo out (parecido al anterior, pero forzosamente debe asignarse valor antes de salir de la función o la aplicación no compilara). Los tipos por "valor", como la estructura, se pasan como indica el nombre por valor, y cualquier modificación que se haga dentro de unas funciones, se perderán completamente la salir de las funciones. Generalmente se intenta que estos tipos sean inmutables (como los enteros o las fechas), para hacerlos más fáciles de usar, y evitar este inconveniente.

Este es un ejemplo de este comportamiento:

private class EjemploPorReferencia
{
 public string Nombre { get; set; }
}
 
private struct EjemploPorValor
{
 public string Nombre { get; set; }
}
 
private static void Funcion(EjemploPorReferencia referencia1, EjemploPorValor valor1, ref EjemploPorReferencia referencia2, ref EjemploPorValor valor2)
{
 //Modifico el contenido de la referencia,
        esto hace que conserve el cambio fuera de la funcion
 referencia1.Nombre = "Nombre refeerncia uno";
 
 //Como se pasa el VALOR de una referencia,
        al asignarle un nuevo objeto se pierde el anterior
 referencia1 = new EjemploPorReferencia { Nombre = "Nombre referencia dos" };
 //Este nuevo objeto recien creado se
        perderna al regregar la funcion, puesto que es una neuva funcion
 //Pero los cambios realizados ANTES de
        asignar el objeto seran conserbados (puesto que se hiceron en la referencia original.
 
 //Este cambio se perdera, puesto que
        las estructuras se pasan por valor siempre y no son referencias
 //como los objetos
 valor1.Nombre = "Nombre estructura una";
 
 //En este objeto la misma referencia
        se pasa por referencia, con lo que se conservan los cambios
 //y ademas si se asigna a otra variable
        (otra estructura) esta se conservara.
 referencia2.Nombre = "Nombre referencia dos"; //se conserva
                el valor
 referencia2 = new EjemploPorReferencia() { Nombre = "Nombre referencia dos,
                creada desde dentro" };
 //Debido a que se asigna un nuevo valor
        y se conserva el ultimo, y no el primero (por el atributo REF).
 
 //En caso la estructura se pasa por referencia,
        con lo que se conservan los cambios
 //y ademas si se asigna a otra variable
        (otra estructura) esta se conservara.
 valor2.Nombre = "Nombre estrura dos"; //se conserva
                el valor
 valor2 = new EjemploPorValor() { Nombre = "Nombre estructura dos,
                creada desde dentro" };
 //Debido a que se asigna un nuevo valor
        y se conserva el ultimo, y no el primero (por el atributo REF).
}
 
private static void Main(string[] args)
{
 //Inicializador de las variables
 EjemploPorReferencia referencia1 = new EjemploPorReferencia { Nombre = "referencia1" };
 EjemploPorValor valor1 = new EjemploPorValor { Nombre = "valor1" };
 EjemploPorReferencia referencia2 = new EjemploPorReferencia { Nombre = "referencia2" };
 EjemploPorValor valor2 = new EjemploPorValor { Nombre = "valor2" };
 
 //Se muestran los valores previos
 Console.WriteLine("VALORES PREVIOS");
 Console.WriteLine(String.Format("Referencia1 :{0}", referencia1.Nombre));
 Console.WriteLine(String.Format("Valor1 :{0}", valor1.Nombre));
 Console.WriteLine(String.Format("Referencia2 :{0}", referencia2.Nombre));
 Console.WriteLine(String.Format("Valor2 :{0}", valor2.Nombre));
 Console.WriteLine();
 
 //llamo a las funciones
 Funcion(referencia1, valor1, ref referencia2, ref valor2);
 
 //Se muestran los valores Actuales
 Console.WriteLine("VALORES ACTUALES");
 Console.WriteLine(String.Format("Referencia1 :{0}", referencia1.Nombre));
 Console.WriteLine(String.Format("Valor1 :{0}", valor1.Nombre));
 Console.WriteLine(String.Format("Referencia2 :{0}", referencia2.Nombre));
 Console.WriteLine(String.Format("Valor2 :{0}", valor2.Nombre));
 Console.WriteLine();
 
 Console.ReadLine();
}
 
 
El resultado esperado de la ejecución de esta función el siguiente:


Liberación de memoria en .NET

.NET, a diferencia de C/C++, tiene un mecanismo de liberación de memoria automático llamado Recolector de Basura, con la que se desentiende de esta tarea al programador, y se elimina la posibilidad de "olvidos" en cuanto a esta tarea, o liberaciones incorrectas (como dobles liberaciones, cuando la memoria ya está siendo usado para otros objetos, etc.).

Los recolectores de basura, no son novedad de .NET o Java, por ejemplo ya existían en Visual Basic 6.0 o Perl u otros más antiguos, en el que la liberación de la memoria, se realizan en cuanto un objeto dejaba de ser usado. Estos mecanismos se llamaban Recolectores de Bausera basando en conteos. Lo que hace es contar las referencias que existen para un objeto y cuanto estas llegan a cero, se libera la memoria relacionada inmediatamente.

Este mecanismo tiene dos inconvenientes, la primera, es que es muy lento, al tener que comprobar el conteo de las variables, cada vez que se liberan. La segunda es que si tenemos una referencia cruzada, digamos entre un objeto A o B, si no se destruye esa relación, los objetos nunca se liberan aunque no existan referencias externas a A o B, puesto que siempre existirá una referencia, la de A a B y viceversa.

El mecanismo de recolección de basura de .NET es diferente, no se basa en conteo, sino en localizar los segmentos de memoria que son accesibles, en un determinado momento. El principio es el siguiente, la liberación de memoria es costosa, y más si es muy repetida, con lo que .NET no libera memoria, a no ser que sea necesario (con lo que siempre da la impresión que las aplicaciones de .NET ocupan mucha memoria, aunque esto es un comportamiento normal). Cuando se produce la necesidad de la liberación, al principio se marca toda la memoria como "sucia" o en "desuso", y se comienza revisando los objetos que todavía están referenciados desde el punto de entrada de la aplicación, dichos objetos se marcan "en uso", y se comienza revisando los objetos referenciaos por los "objetos" en uso, y a su vez se marcan "en uso", y se repite la operación. Al final los objetos que están marcados "en uso", son conservados en memoria, y el resto que sigue marcado como memoria "sucia" es liberado. De esta forma el proceso es más rápido y menos costoso, a la vez que se soluciona el problema de objetos referenciados entre sí puesto que si no hay ningún otro objeto que los referencia, se marcaran como "sucios" (puesto que no hay manera de llegar a ellos desde un punto externo a sí mismos) y se liberan sin problemas.

El proceso es válido (y automático) para objetos de .NET, pero por ejemplo para liberar componentes como ActiveX de manera segura, es necesario hacerlo explícitamente con el comando Marshal.FinalReleaseComObject(COM), sino dicho memoria, seguirá siendo consumida indefinidamente y posiblemente aumentando su uso.

Identidad y tamaño de los objetos

Los objetos en C#, tienen asociada su identidad y los array su tamaño, a diferencia de C++ en el que no hay forma de conocer el tipo de un objeto o el tamaño de un array teniendo exclusivamente dicho array u objeto.

En .NET es siempre posible recuperar la identidad del objeto con el método, GetType, a la vez que se puede comprobar si un objeto es de un tipo determinado con el operador is.

EjemploPorReferencia referencia1
= new EjemploPorReferencia();
 
//Obtengo el tipo
Type tipo = referencia1.GetType();
//Cambien puedo comprobar el tipo, de
    esta forma
if (tipo is EjemploPorReferencia)
{
 Console.WriteLine("El tipo es referencia");
}
 

Igualmente el compilador nos impide realizar cast inválidos, advirtiéndonos de esta circunstancia como un error.


Aunque se puede "engañar" al compilador dando un rodeo a la asignación que compilara perfectamente, pero sin embargo dará un excepción que interrumpirá el flujo normal del programa (a diferencia de C/C++ en el que la ejecución del programa continuara, hasta que eventualmente generar un comportamiento inesperado).


Algo semejante ocurrida cuando intentamos acceder a una posición invalidad dentro de un array (nuevamente C nos permitirá hacerlo y c#, generara una excepción).


Igualmente podemos comprobar el tamaño de los array con la propiedad Length. Por otro lado .NET nos facilita el acceso a los array con el comando foreach, de forma que no tenemos que trabajar con índices dentro de un array o una lista (además este comando para más seguridad impide las modificaciones del objeto que se esté recorriendo).

private static void Funcion4()
{
 EjemploPorReferencia[] referencias = new EjemploPorReferencia[10];
 foreach (EjemploPorReferencia referencia in referencias)
 {
  //Trabajo directamente con el objeto
            referencia en lugar de con un indice.
 }
}
 

Homogeneidad de arquitecturas

En .NET, en cualquier sistema, e independientemente si la aplicación es de 64 o 32 bits, el tamaño de los enteros y demás valores, siempre tiene el mismo tamaño, y las clases de tipo string son del mismo tipo (Unicode). El efecto es nos podemos abstraer del tipo de dato y el tamaño de esto, y dejar esos aspectos de bajo nivel al compilador, a diferencia de C, en el que los tenemos que tener en cuenta, la mayoría de las veces, para evitar futuros problemas en nuestra aplicación al momento de cambiar de arquitectura o interconectar distintos sistemas entre sí

Interrupción del flujo de ejecución en caso de errores.

Cuando tenemos una acceso de memoria incorrecto en C/C++, muchas veces no somos notificados por ello (porque no hay mecanismos para detectar estas circunstancias), sin embargo en .NET existen una seria de excepciones que controlan explícitamente este tipo de errores e interrumpen el flujo ejecución del programa, para que esta condición sea detectada, y corregida adecuadamente.

Algunas excepciones relacionadas con el control de acceso a la memoria son las siguientes:

  • InvalidCastException: No se puede realizar un cast, entre un tipo de objeto y otro.

  • IndexOutOfRangeException: Se está intentando a acceder a un índice inexistente dentro de un array.
  • NullReferenceException: Se está intentado usar un objeto que no se ha inicializado (con el comando new).
  • AccessViolationException: Se está intentado acceder a una posición de memoria invalida (ocurre cuando estamos conectando sistema de .NET con sistema en otras tecnologías).

Uso de punteros en C#

El uso de punteros tradicionales como en C/C++ es posible realizarlo también en C#, aunque es difícil encontrar situaciones donde esto será realmente necesario, para realizarlo se debe configurar los segmentos de código de la aplicación como inseguros (unsafe) del siguiente modo:

 
class UnsafeTest
{
   // Unsafe method: takes pointer to int:
   unsafe static void SquarePtrParam(int* p)
   {
   *p *= *p;
   }
 
   unsafe static void Main()
   {
   int i = 5;
   // Unsafe method: uses address-of operator
          (&):
   SquarePtrParam(&i);
   Console.WriteLine(i);
   }
}
// Output: 25
 

En estos contexto no se realizan las validaciones por defecto que se hacen en C# "seguro", por eso no es tan común el uso de "punteros" tradicionales en C#, y en principio debiera evitarse, su existencia parece deberse exclusivamente a interacción de bajo nivel con componentes creados en C o C++.