lunes, 31 de marzo de 2014

App - OrtizOL | Backup Timer

Tabla de Contenido

Introducción
1. OrtizOL | Backup Timer
2. Principales Funciones
3. Documentación
3.1 Arquitectura Básica
3.2 Operación
3.3 Limitaciones
4. Capturas de Pantalla
5. Requisitos de Sistema
6. Descarga
6.1 Ejecutable
6.2 Código Fuente
Conclusiones
7. Conclusiones
8. Glosario
9. Referencias

Introducción

Blogger cuenta con un sistema de auto-guarado eficiente, sin embargo, no está demás realizar copias de seguridad acumulativas a medida que se progresa en la redacción de un artículo, receta, ejercicio, aplicación (como este mismo documento de arquitectura básico), &c. Actualmente utilizo la aplicación Cook Backup Timer desarrollada por Diaa Mahmoud Sami, a lo que decide crear la propia mía a partir del ejercicio natural de imitación. A continuación les presento los detalles de arquitectura básica de OrtizOL | Backup Timer.

1. OrtizOL | Backup Timer

OrtizOL | Backup Timer es una utilidad de escritorio (standalone) que facilita la programación de temporizadores en cantidades de tiempo predeterminadas y también las propias personalizadas. Es una aplicación que emita la interfaz de usuario y la funcionalidad de una ya desarrollada: Cook Backup Timer:
Pantalla principal Cook Timer
Figura 1. Pantalla principal Cook Timer.
Y esta es la pantalla principal de OrtizOL | Backup Timer:
Pantalla principal de OrtizOL | Backup Timer
Figura 2. Pantalla principal de OrtizOL | Backup Timer.
A ojo desnudo, son pocas las diferencias a distinguir. De ahí que considere que el ejercicio de imitación es una actitud humana natural, y que tiene grandes ventajas en el proceso de aprendizaje autónomo.

2. Principales Funciones

Estas son las principales de la aplicación:
  • Crear temporizador a modo de recordatorio para actividades/tareas rutinarias e importantes.
  • Uso de tiempo predeterminado (3, 5, 10, y 15 minutos).
  • Especificación manual de temporizador personalizado.
  • Inicio, pausa, reanudación, y reinicio de temporizador.
  • Reinicio automático de temporizador.
  • Timbre permanente de temporizador completado.

3. Documentación

A continuación describiré los elementos documentales básicos de la apilicación: arquitectura básica, y su operación.

3.1 Arquitectura Básica

Domininio del problema:
Modelo del dominio del problema.
Figura 3. Modelo del dominio del problema.

Interfaz Gráfica:
Modelo de GUI
Figura 4. Modelo de GUI.

Despliegue:

Despliegue
Figura 3. Diagrama de Despliegue

3.2 Operación

Aquí describiré cómo llevar a cabo la programación de un temporizador personalizado.

Abrimos la aplicación y selección la opción 'Custom':
Selección opción Custom
Figura 4. Selección opción Custom.

Establecemos el tiempo desde los controles 'Hours', 'Minutes', y 'Seconds':
Selección Tiempo Personalizado
Figura 5. Selección Tiempo Personalizado.
Clic sobre el botón 'Start':
Clic en Start
Figura 6. Clic sobre el botón 'Start'.

Finalmente, el temporizador inicia la cuenta regresiva:
Temporizador en progreso.
Figura 7. Temporizador en progreso.
Demostración en vídeo:

3.3 Limitaciones

Entre las limitaciones identificadas están:
  • Interfaz de usuario en un sólo idioma: inglés.
  • Sólo permite mantener un temporizador en la marcha.
[Nota: Esta es una versión ALPHA. Aún posee problemas de concurrencia (estas serán corregidas en un futuro próximo.]

4. Capturas de Pantalla
Interfaz principal de OrtizOL | Backup Timer
Figura 8. Interfaz principal de OrtizOL | Backup Timer.

5. Requisitos del Sistema

  • Hardware:
    • Procesador: Intel o compatible (x86, x64)
    • Memoria RAM: 128MB
  • Software:
    • Sistema Operativo: Windows XP o superior.
    • Plataforma: Microsoft .NET Framework 3 o superior.

6. Descarga

El archivo de ejecución puede ser descargado desde el siguiente enlace:

6.2 Código Fuente C#

Enlace de descarga del código fuente de la solución:

[Subiendo]

7. Conclusiones

En el desarrollo de esta utilidad de temporizador se ha empezado a comprender el uso de componentes de concurrencia en el lenguaje  C#. Además, cómo construir interfaces gráficas de usuario utilizando un editor de texto plano (Notepad++). Continuo haciendo énfasis en el uso de editores de texto plano en el proceso temprano de aprendizaje de un lenguaje de programación.

8. Glosario

- GUI
- Standalone

9. Referencias

[1]: xCSw


H

lunes, 3 de marzo de 2014

Comprobación de Tipos en Tiempo de Compilación y Ejecución en C#

Tabla de Contenido

0. Introducción
1. Ciclo de Vida del Proceso de Compilación
1.1 Análisis léxico
1.2 Análisis semántico
1.3 Análisis sintáctico
1.4 Generación de código intermedio
2. Sistema de Tipos
3. Modos de Comprobación de Tipos
3.1 Estático
3.1.1 Tipeo fuerte
3.1.2 Tipeo débil
3.2 Dinámico
3.2.1 Dinamismo en la plataforma .NET
3.2.2 Dynamic Language Runtime (DLR)
4. Conclusiones
5. Glosario
6. Enlaces & Literatura

0. Introducción

En este espacio nos vamos a adentrar en el entendimiento de la comprobación de tipos en tiempo de compilación y ejecución. Hemos aprendido que tanto el compilador y la CLR de C# proveen mecanismos que automatizan muchas tareas que de lo contrario el programador tendría que hacer a pulso: liberación y localización de memoria,  manejo de excepciones, comprobación de tipos, &c. La infraestructura de .NET y en consecuencia del lenguaje de programación nos ayuda a desentendernos de estos asuntos; y el sistema de tipos nos ayudará a detectar problemas en la manipulación de tipos. Veamos cómo. Bienvenidos.

1. Ciclo de Vida del Proceso de Compilación

El proceso (ciclo de vida) de compilación [4] está compuesto por, principalmente, las siguientes fases:
  • Análisis léxico
  • Análisis semántico
  • Análisis sintáctico
  • Generación de código intermedio
En la Figura 1 [4] se describe visualmente este proceso.
Ciclo de vida compilación.
Figura 1. Ciclo de vida compilación [4].

1.1 Análisis léxico

Durante el análisis léxico [2] el código fuente de nuestro programa es fragmentado en bloques de cadenas de texto útiles para las siguientes fases del proceso. Estas unidades fundamentales son conocidas como lexemas.

1.2 Análisis semántico

Este análisis comprende la generación de significado para la diferentes formas de la especificación del lenguaje. Básicamente, provee la infraestructura para analizar el significado de una sentencia, bloque de código, uso correcto de tipos, entre otros.

1.3 Análisis sintáctico

En esta fase se lleva a cabo el análisis del código que hemos escrito y validar que cumpla las reglas de todas las construcciones del lenguaje (esquema de palabras clave o reservadas, uso de operadores, separadores de sentencias, &c.). Esta fase producirá el árbol sintáctico.

1.4 Generación de código intermedio

La generación de código intermedio consiste en producir código para optimización (basado en la plataforma, máquina virtual).

2. Sistema de Tipos

Los lenguajes de programación modernos, claro como C#, cuentan con un sistema de tipos. Este sistema abstrae las restricciones, estado, comportamiento, operaciones de los tipos de datos definidos, y éstos a su vez le dan significado a los datos que manipulan. Sobretodo, el sistema de tipos obliga a que las manipulaciones sobre los datos sigan las reglas establecidas sobre el tipo de dato [2].

Los lenguajes de programación que cuentan con un sistema de tipos, pueden llevar a cabo esta tarea, ya sea estáticamente, o dinámicamente.

[Nota: Recomiendo la lectura de mi artículo Seguridad de Tipos en C# para conocer más sobre este sistema.]

3. Modos de Comprobación de Tipos

3.1 Estático

Un lenguaje de programación que implemente el sistema de tipos de manera estática, ejecuta todas las rutinas de comprobación de tipos en tiempo de compilación. Cualquier error directo o potencial es detectado antes de generar el programa (código) objeto. Sin embargo, hay que agregar que dependiendo de la perspicacia del compilador, algunos errores pueden pasar por alto, y ser sólo detectados en tiempo de ejecución.

El modo estático para el sistema de tipos, agrega una capa de protección para la detección proactiva de estos errores [2]. Adicionalmente, la verificación en los lenguajes de programación puede variar conociendo que sean fuerte o débilmente tipeados.

3.1.1 Tipeo fuerte

C# es un lenguaje de programación que cabe en esta categoría. Las comprobaciones de tipos se realizan en tiempo de compilación. Por ejemplo, si en una supuesta expresión aritmética como:

"1" + 1

se genera un error en tiempo de compilación:

error CS0029: Cannot implicitly convert type `string' to `int'

Lo que requiere un tratamiento conocido como conversión. Será una conversión explícita que transforme la cadena "1" en un valor numérico computable. Por ejemplo esta última cadena a entero de 32 bits (int) podemos utilizar el método ToInt32 [6] de la clase Convert [5]:

Convert.ToInt32( "1" ) + 1

También en esta categoría caben los operadores de conversión explícitos, como por ejemplo:

(Triangulo) figura;

Otros lenguajes de programación que siguen este mismo paradigma:
  • Java
  • F#

3.1.2 Tipeo débil

Corresponde con los lenguajes de programación que no distinguen de tipos de datos y llevan a cabo las operaciones (detrás de cámara) que asumen y entienden de qué se trata la expresión, por ejemplo la expresión "1" + 1 en Perl [7] es completamente válida, y resultará en 2.

3.2 Dinámico

Cuando hablamos de comprobación de tipos dinámico, nos referimos a las operaciones del sistema de tipos que son llevadas en tiempo de ejecución (anglicismo: runtime). Todas las verificaciones (capacidades, restricciones, operaciones, estado, &c.) de un tipo, se operan en tiempo de ejecución mientras nuestra aplicación se ejecuta. Esto ofrece la garantía frente a pruebas reales del flujo de ejecución de las aplicaciones que estemos próximos a lanzar. En  consecuencia, nos da la garantía (cuasi 100%) de que cuando la aplicación entre en producción  estará libre de bugs (errores).

Entre las utilidades de la comprobación de tipos dinámico, tenemos [2]:
  • Fácil y eficiente testing unitario.
  • Para scripting multiplataforma
  • Runtime reflection [8]
Ejemplos de lenguajes de programación de esta categoría [2]:
  • Python
  • Javascript
  • PHP
  • Perl
  • Lisp
  • Ruby

3.2.1 Dinamismo en la plataforma .NET

En el Framework .NET se cuenta con la infraestructura (librerías, construcciones de lenguaje, &c.) necesaria para alcanzar un verdadero dinamismo [2]. Aunque este dinamismo puede lograr por diferentes medios, aquí trataré con reflection [8][9].

Veamos un ejemplo para comprender mejor este concepto.

Archivo ClaseFactorial.cs:



Esta clase sólo tiene construcciones elementales de una clase. (Nuevo término: POCO - Plain Old C# Object: una clase con definiciones elementales.)

A través de reflection podemos introducir el dinamamismo utilizando construcciones avanzadas para la creación de una de instancia de la clase ClaseFactorial y la consecuente ejecución del método ComputarFactorial. Así:

Assembly assem = Assembly.GetExecutingAssembly();
object factorial = Activator.CreateInstance( assem.GetType ("ClaseFactorial"));
Type tipoFactorial = factorial.GetType();
MethodInfo metodoFactorial = tipoFactorial.GetMethod("ComputarFactoral");
object resultado = metodoFactorial.Invoke (factorial, new object[] {10});
int resultadoFactorial = Convert.ToInt32 (resultado);
Console.WriteLine (resultadoFactorial);

3.2.2 Dynamic Language Runtime (DLR)

En [2] se explicita:

"The DLR (Dynamic Language Runtime) adds a set of libraries which makes doing the above much easy and fun. It adds a set of features designed specifically to meet the needs of dynamic languages such as a shared dynamic type system, a common hosting model and abilities to generate fast dynamic code and fast symbol tables."
Además, la DLR está disponible desde la versión 4.0 del Framework .NET. En la Figura 2 [2] se muestra cómo está integrada la DLR sobre la Common Language Runtime (CLR).
DLR soportada por la Common Language Runtime (CLR)
Figura 2. DLR soportada por la Common Language Runtime (CLR) [2].
Ahora observemos en la Figura 3 [2] cómo DLR permite la interoperabilidad con múltiples lenguajes de programación compatibles con .NET:
Soporte de .NET para DLR.
Figura 3. Soporte de .NET para DLR [2].

4. Conclusiones

Grosso modo vimos el ciclo de vida del proceso de compilación. De aquí, precisamente desde la fase de Análisis Sintáctico, extrajé el concepto de sistema de tipos el cual nos proporcioná los mecanismos para hacer validaciones sobre los tipos que usamos para manipular datos. Aprendimos que este sistema funcionada en modo estático y dinámico; en el caso de éste último, observamos que el Framework .NET provee los mecanimos necesarios para soportar programación dinámica. Al final vimos como el DLR está soportado por la CLR y el Framework .NET.

5. Glosario

  • Compile time
  • Dinamismo
  • DLR
  • Perl
  • PHP
  • Reflection
  • Ruby
  • Runtime

6. Enlaces & Literatura

[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[2]: Infosys.NET Framework - dynamic-language-runtime.pdf - http://www.infosys.com/microsoft/resource-center/Documents/dynamic-language-runtime.pdf
[3]: The Type System - http://www.pearsonhighered.com/assets/hip/us/hip_us_pearsonhighered/samplechapter/0201770180.pdf
[4]: Compiler, the free encyclopedia - https://en.wikipedia.org/wiki/Compiler
[5]: Convert Class (System) - http://msdn.microsoft.com/en-us/library/vstudio/system.convert%28v=vs.100%29.aspx
[6]: Convert.ToInt32 Method (System) - http://msdn.microsoft.com/en-us/library/vstudio/system.convert.toint32%28v=vs.100%29.aspx
[7]: Perl, the free encyclopedia - https://en.wikipedia.org/wiki/Perl
[8]: Reflection (computer programming), the free encyclopedia - https://en.wikipedia.org/wiki/Reflection_%28computer_programming%29
[9]: Reflection in the .NET Framework - http://msdn.microsoft.com/en-us/library/f7ykdhsy%28v=vs.110%29.aspx


J

sábado, 1 de marzo de 2014

Boxing y Unboxing en C#

Tabla de Contenido

0. Introducción
1. Tipos por Valor y Tipos por Referencia
1.1 Tipos por Valor
1.2 Tipos por Referencia
2. Stack y Heap
2.1 Stack
2.2 Heap
3. Boxing y Unboxing
4. Rendimiento
5. Preguntas y Respuestas
6. Conclusiones
7. Glosario
8. Enlaces & Literatura

0. Introducción

En este artículo explicaré cómo se lleva a cabo los procesos de boxing y unboxing (prefiero utilizar los términos anglosajones para evitar traducciones vulgares) en C#. Dos operaciones que son inherentes al sistema unificado de tipos de C#. Empezaré por aclarar (brevemente) los conceptos de tipos por valor y tipos por referencia; que nos sirve para afianzar las operaciones mencionadas. También incluiré la descripción de excepciones que pueden ocurrir mientras que laboramos con boxing y boxing. Trataré de la deficiencia en el rendimiento si abusamos de estas conversiones (independiente de la dirección). Incluiré ejemplos para afianzar lo comprendido a través de la práctica. Bienvenidos.

1. Tipos por Valor y Tipos por Referencia

A pesar que en el artículo Tipos por Valor y Tipos por Referencia en C# traté más a fondo este tema, voy a destacar las características básicas de estos tipos para introducir posteriormente las operaciones protagonistas de este artículo.

1.1 Tipos por Valor

Los tipos por valor (también conocidos como tipos primitivos, o tipos integrados) no son más que aquellas literales numéricas utilizadas para las operaciones aritméticas. Las clasificación de estos tipos es la que se muestra en la Figura 1 [1].
Tipos numéricos predefinidos en C#
Figura 1. Tipos numéricos predefinidos en C# [1].
La clase padre de todas estas categorías corresponde con ValueType [9]. Todos los valores para estas categorías son almacenados en una locación conocida estructura stack (tema de la siguiente sección).

A pesar de que este tipo de operación está permitida:

System.ValueType v = 13;

Debido a que la literal 13 es un subtipo, para precisar int (alias de Int32), de ValueType. Una operación aritmética como esta:

System.ValueType v1 = 13;
System.ValueType v2 = 6;

System.ValueType v3 = v1 + v3;

no está permitida en el lenguaje, debido a que ValueType es un tipo por referencia y no existe una versión sobrecargada del operador de suma (+) para alcanzar el resultado que esperamos.


Error que obtenemos:

error CS0019: Operator `+' cannot be applied to operands of type `System.ValueType' and `System.ValueType'

1.2 Tipos por Referencia

Empezando por el tipo object (recomendad lectura de mi artículo El Tipo object en C#) todo tipo de objeto, implícitamente, es un tipo por referencia. Otra evidencia de los tipos de datos por referencia son aquellos que se almacenan en la locación/estructura especial conocida como heap (se tratará en la siguiente sección). Cualquier clase que ya sea parte del Framework .NET o una definida por un programador es considerada un tipo por referencia.

En [8], además dicen:
"C# new operator returns the memory address of the object."

2. Stack y Heap

Introduciré los conceptos de Stack y Heap para comprender las operaciones de boxing y unboxing.

[Nota: Estas dos estructuras de almacenamiento se hayan más ampliamente explicadas en mi artículo Variables y Parámetros en C# - Parte 1.]

2.1 Stack

En [1] se define stack como: en arquitecturas de computación, un stack no es más que una región de memoria en donde los datos son removidos de acuerdo al modo primero-en-entrar-primero-en-salir (o inglés, LIFO - Last-In-First-Out [10]), es decir, que es posible extraer el último elemento de la parte superior de la pila, los demás no son accesibles. Es por eso, que a esta estructura es funcionalmente limitada, pero útil para infinidad de aplicaciones de almacenamiento de datos en tiempo de ejecución.

2.2 Heap

El heap al igual que el stack, es un bloque de memoria usado para almacenar objetos (i.e., instancias de tipos por referencia [1]). Cuando el programador declara e inicializa un objeto de una clase en particular, este objeto es almacenado en esta región de memoria especial, finalmente, retorna la referencia hacia esa locación y queda señalada por el identificador(es) declarado.

3. Boxing y Unboxing

Como aclaré desde el principio, prefiero utilizar los términos anglosajones para estas operaciones en lugar de incurrir en una traducción subjetiva que resulte vulgar. A continuación describiré conceptualmente el propósito de estas operaciones, además incluiré ejemplos concretos de su uso.

3.1 Boxing

De acuerdo con [1] y [3], la operación de boxing consiste en convertir un tipo por valor en un tipo por referencia. El tipo por valor debe implementar la interfaz o haber heredado desde la clase padre, abuelo, &c.

Por otro lado, todos los valores pasados a un tipo por referencia se localizarán en la estructura heap y el valor como tal será almacenado en el nuevo objeto creado a partir de la operación boxing.

Miremos esta operación a través de código fuente C#:

Creamos una variable entera (int):

int i = 123;

Luego copiamos el valor de esa variable en un objeto tipo object:

object o = i; // boxing implícito

O también esta versión:

object o = (object)i; // boxing explícito

En esta sentencia creamos una referencia -o-, que se localizará en el stack, la cual referenciará al valor de tipo int en el heap. En la Figura 2 [3] se describe pictóricamente este proceso. En la segunda versión se utiliza el operador de casting (object) para ejecutar un boxing explícito.
Figura 2. Proceso de boxing [3].

3.1.1 Ejemplo

En este ejemplo presento la versión completa del código anterior; además, haré énfasis en la diferencia de hacer unboxing sobre el valor de la variable y sobre la locación de la misma; esto se debe a que ambas locaciones de memoria son diferentes: los valores tienen asignadas ubicaciones diferentes. En [1] llaman a este efecto copiado de semántica.

Archivo BoxingPueba.cs:

Detallemos que a pesar de que hemos cambiado el valor de la variable i en la línea 11, esto no afecta el valor previo que almacenamos sobre la variable object o.

3.2 Unboxing

Con base en [1] y [3], puedo parafrasear que, la operación de unboxing consiste en convertir un objeto tipo object en un tipo por valor. La conversión también se puede realizar desde una interfaz que el tipo por valor implemente. Vale añadir [3], que esta operación consiste en:
  • La compatibilidad del tipo por referencia con el tipo por valor.
  • Copiado del valor del tipo por referencia al tipo por valor.
Veamos este fragmento de código:

int i = 123;
object o = i; // boxing implícito

int j = (int)o; // unboxing

Obsérvese el uso de el casting explícito en la última línea. La CLR se encarga de realizar esta operación .

Este fragmento tiene su equivalente, y está descrito en la Figura 3 [3].
Proceso de unboxing.
Figura 3. Proceso de unboxing [3].

3.2.1 Ejemplo (Excepciones)

En este ejemplo veremos que el intento de hacer boxing sobre tipos no compatibles, generará la excepción InvalidCastException [2]. Su nominación indica que se trata de una excepción lanzada cuando hay una conversión -casting- inválida.

Archivo UnboxingExcepcion.cs:


A pesar de que no hemos tratado el tema de excepciones, lo que básicamente hacemos en las líneas 11-20 es capturar cualquier posible error que finalice de forma abrupta con el flujo de ejecución de la aplicación, en su lugar, preferimos tratar la excepción, en este caso mostrar un mensaje de error.

Otra excepción que se puede lanzar mientras tratamos de hacer unboxing es NullReferenceException [11]. La cual se activa cuando tratamos con una referencia null en el proceso de unboxing.

4. Rendimiento

De acuerdo con [4], esta es la consideración a tener en cuenta a la hora de trabajar con las operaciones boxing y unboxing:
"It is best to avoid using value types in situations where they must be boxed a high number of times, for example in non-generic collections classes such as System.Collections.ArrayList. You can avoid boxing of value types by using generic collections such as System.Collections.Generic.List. Boxing and unboxing are computationally expensive processes. When a value type is boxed, an entirely new object must be created. This can take up to 20 times longer than a simple reference assignment. When unboxing, the casting process can take four times as long as an assignment. For more information, see Boxing and Unboxing."
En resumen, la operación de unboxing requiere 20 veces más recursos que la simple operación de asignación de referencias. Por otro lado, la operación de unboxing, puede tomar hasta 4 veces más recursos. Así que debemos tener mucho cuidado al tratar estas operaciones en programas de alta disponibilidad.

5. Preguntas y  Respuestas

En Stack Overflow hay un par de preguntas interesantes en las que podemos profundizar profundizar, esas son:
  1. Operaciones boxing y unboxing de tipos int y string: [6]
  2. ¿El porqué de las operaciones boxing y unboxing?

6. Conclusiones

Aprendimos acerca del concepto de boxing (pasar un tipo por valor a uno por referencia), y su opuesta, la operación unboxing (conversión de un tipo por referencia a uno por valor). Estas operaciones son gestionadas por la CLR sobre las estructuras de datos stack y heap. En los ejemplos apreciamos cómo podemos capturar un entero (int) sobre un objeto object; así mismo, también observamos el manejo de excepciones para evitar terminaciones abruptas de las aplicaciones cuando se ha tratado de ejecutar una operación unboxing. Al final nos quedó claro que estas dos operaciones son costosas, en términos de ciclos de procesador y espacio en memoria.

7. Glosario

  • Boxing
  • Clase
  • CLR
  • Heap
  • Tipos por referencia
  • Tipos por valor
  • Stack
  • Unboxing

8. Enlaces & Literatura

[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[2]: InvalidCastException Class (System) - http://msdn.microsoft.com/en-us/library/system.invalidcastexception%28v=vs.110%29.aspx
[3]: Boxing and Unboxing (C# Programming Guide) - http://msdn.microsoft.com/en-us/library/yz2be5wk.aspx
[4]: Performance (C# and Visual Basic) - http://msdn.microsoft.com/en-us/library/ms173196.aspx
[5]: Boxing And Unboxing C## Help | C# Help - http://www.csharphelp.com/2006/02/boxing-and-unboxing-c/
[6]: c# - boxing and unboxing in int and string - Stack Overflow - http://stackoverflow.com/questions/6423452/boxing-and-unboxing-in-int-and-string
[7]: .net - Why do we need boxing and unboxing in C#? - Stack Overflow - http://stackoverflow.com/questions/2111857/why-do-we-need-boxing-and-unboxing-in-c
[8]: Boxing and UnBoxing in C# - http://www.codeproject.com/Articles/8100/Boxing-and-UnBoxing-in-Csharp
[9]: ValueType Class (System) - http://msdn.microsoft.com/en-us/library/system.valuetype%28v=vs.110%29.aspx
[10]: [5] LIFO (computing) - Wikipedia, the free encyclopedia - http://en.wikipedia.org/wiki/LIFO_(computing)
[11]: NullReferenceException Class (System) - http://msdn.microsoft.com/en-us/library/system.nullreferenceexception.aspx


J