domingo, 31 de agosto de 2014

Pregunta C# (5 de 20): ¿Cómo Invocar el Constructor de una Clase Base?

Índice

0. Introducción
1. Contexto
1.1 ¿Qué es un constructor?
1.2 ¿Cómo se define un constructor?
2. Métodos de Invocación de un Constructor de una Clase Base
2.1 Método 1: Forma básica
2.2 Método 2: Modificación temprana de argumentos de constructor base
2.3 Método 3: Patrón factory
3. Artefactos y Recursos
4. Conclusiones
5. Glosario
6. Literatura & Enlaces

0. Introducción

Esta pregunta constituye la número 5 del curso de Twenty C# Questions Explained de Microsoft Virtual Academy (MVA). Ahora entraremos en los detalles del proceso de invocación del constructor de una clase base (o superclase) a partir de una subclase de la jerarquía de herencia en un dominio específico. Conoceremos específicamente 3 métodos para realizar esta tarea: uso estándar, modificación temprana del argumento o cualquier otra operación antes de invocar el constructor de la clase base, y la creación de un clase con el patrón factory.

1. Contexto

1.1 ¿Qué es un constructor?

Los constructores son métodos especiales encargados de la inicialización del estado de una instancia u objeto a crear. Veremos que existe una diferencia sutil entre un método y un constructor: éste último en su definición no especifica un valor de retorno (ni siquiera void).


[Nota: Recomiendo la lectura acerca de constructores en su versión extendida: Constructores de Instancia.]

1.2 ¿Cómo se define un constructor?

Para definir un constructor en el cuerpo de declaración de una clase ya sea abstracta o concreta, seguimos la siguiente especificación sintáctica:

public class Superclase
{
{modificador-acceso} Superclase({lista-parametros})
{
// Cuerpo de declaración del constructor
}
}

Debemos especificar un modificar de acceso (cfr. Modificadores de Acceso), omitimos el tipo de retorno y finalmente el nombre del constructor debe corresponder con el nombre de la clase donde se haya declarado, en este caso Superclase, y finalmente, el conjunto o lista de parámetros para la inicialización del estado del objeto.

1.3 Uso de un constructor

Para hacer uso de un constructor de código cliente es necesario combinar el nombre de la clase junto con los parámetros de inicialización y el operador de instanciación new:

SuperClase objSc = new SuperClase({lista-parametros});

2. Métodos de Invocación de un Constructor de una Clase Base

A continuación describiremos tres formas básicas de la invocación de un constructor desde una clase subclase sobre una jerarquía de herencia.

2.1 Método 1: Forma básica

La primera forma consiste en la más básica, simple, y directa de invocar un constructor de una clase base, por ejemplo, para la inicialización de miembros de la superclase. Para demostrar su uso utilicemos la siguiente jerarquía de herencia de Persona:
Jerarquía de Herencia Persona
Figura 1. Jerarquía de herencia Persona.
Ahora escribamos las clases implementadas en código fuente C#; empezando por la clase abstracta Persona:

En las líneas 23-26 declaramos el constructor de la clase abstracta Persona y especificamos como único parámetro nombrePersona de tipo string.

Ahora pasemos a escribir la clase Estudiante que hereda de forma directa de la clase Persona:

Para empezar, en la línea 5 especificamos la herencia directa de la clase Estudiante desde la clase Persona. Ahora el punto importante que queremos resaltar: sobre la línea 24 utilizamos la palabra clave base [4] seguida de paréntesis con el conjunto de argumentos de uno de los constructores de la clase base, específicamente, el constructor con un solo parámetro -nombrePersona-. Luego en el cuerpo del constructor de Estudiante efectuamos la asignación del carnet del estudiante. Por motivos de simplicidad creamos el método Main (líneas 29-35) para crear una instancia de Estudiante y pasar como argumentos al constructor el nombre del estudiante y su respectivo carnet de identidad:

public Estudiante (string, string)


Ahora procedamos a compilar, ejecutar, y probar estos artefactos.


Compilación:


  1. csc /target:exe Estudiante.cs Persona.cs

Ejecución assembly:


  1. .\Estudiante.exe

> Prueba de ejecución (ideone.com).

> Prueba de ejecución (local):
Ejecución assembly Estudiante.exe
Figura 2. Ejecución assembly Estudiante.exe.

2.2 Método 2: Modificación temprana de argumentos de constructor base

Antes de pasar un argumento a un constructor de clase base (superclase) podemos alterar su contenido o representación de acuerdo a una lógica arbitraria que deseemos especificar para nuestros artefacto. De ahí que llamemos a este método modificación temprana de argumentos de constructor. Pasemos a una demostración concreta de este método para conocer su uso y utilidad.

Partimos de la misma jerarquía de herencia modelada en la Figura 1; ahora lo que tenemos que hacer es crear la clase Empleado:

Resaltemos en esta archivo C# el constructor de la clase Empleado en las líneas 23-27; en este caso la invocación al constructor de la clase base Persona, antes de pasar el valor que corresponde con el nombre del empleado su representación es pasada a mayúsculas (simulación de un requerimiento para los nombres de los empleados), esto se logra a través de la invocación del método CambiarMayusculas (líneas 30-33):

private static String CambiarMayusculas(string)


Vale mencionar que este método debe ser static para ser invocado, debido a que antes de crear la instancia sólo se pueden invocar miembros que cumplan esta característica, de lo contrario se generará el error CS0120 [5].


Compilación:


  1. csc /target:exe Empleado.cs Persona.cs

Ejecución assembly:


  1. .\Empleado.exe

> Prueba de ejecución (ideone.com).

> Prueba de ejecución (local):
Ejecución assembly Empleado.exe
Figura 3. Ejecución assembly Empleado.exe.

2.3 Método 3: Patrón factory

Otra de las características importantes sobre el alcance de un constructor es que podemos hacer que sólo tenga acceso o visibilidad sobre la clase en donde es declarado, es decir, private. Esto nos sirve para implementar el patrón factory [6], un patrón del tipo de creación que básicamente consiste en especificar un método static que se encarga de crear los objetos de una clase específica sin el uso del operador new desde código cliente. Veamos un fragmento de código C# para comprender específicamente de que estamos hablando:

public class Subclase : Superclase
{
private Subclase(string cadena) : base(cadena)
{
// implementación
}

// Método para la creación de objetos Subclase:
public static Subclase MetodoFactory(string cadena)
{
return new Subclase(cadena);
}
}

3. Artefactos y Recursos

Conjunto de artefactos producidos a lo largo del desarrollo de la explicación de esta pregunta acerca de la invocación de constructores:
Este es el vídeo en donde el equipo de expertos (Gerry O'Brein y Paul Pardi) de MVA responden y explican esta pregunta:

4. Conclusiones

Con este nuevo conocimiento de cómo invocar un constructor de una clase base, ya podemos prestar más atención a casos sutiles en donde se requiere cierta pericia a la hora de implementar un mundo o dominio de un problema. En la próxima pregunta C# explicaremos cómo contar el número de ocurrencias de una cadena de caracteres dentro de un objeto String.

5. Glosario

  • Argumento
  • Base
  • Clase padre
  • Constructor
  • Herencia
  • Jerarquía
  • Parámetro
  • Subclase
  • Superclase

6. Literatura & Enlaces

[1]: Twenty C# Questions Explained - http://www.microsoftvirtualacademy.com
[2]: Constructores de Instancia en C# | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2013/10/constructores-de-instancia-en-c.html
[3]: OrtizOL - Experiencias Construcción Software (xCSw): Modificadores de Acceso en C# - http://ortizol.blogspot.com/2014/04/modificadores-de-acceso-en-c.html
[4]: base (C# Reference) - http://msdn.microsoft.com/en-us/library/hfw7t1ce.aspx
[5]: Compiler Error CS0120 - http://msdn.microsoft.com/en-us/library/s35hcfh7.aspx
[6]: Factory method pattern - Wikipedia, the free encyclopedia - https://en.wikipedia.org/wiki/Factory_method_pattern


A

sábado, 30 de agosto de 2014

Composición de Secuencias en C#

Índice

0. Introducción
1. ¿Qué es una Secuencia?
2. Implementación de una Secuencia en C#
3. Conclusiones
4. Glosario
5. Literatura & Enlaces

0. Introducción

Desarrollaremos este artículo C# para comprender cómo componer secuencias de elementos en C#. Veremos que esta operación guarda una relación importante con el quehacer del programador a diario, en particular, en tareas relacionadas con la enumeración de elementos de una estructura de datos o un generador de valores. Además, resaltaremos la flexibilidad con que esta tarea de composición de secuencias se puede llevar a cabo, y que a partir de este concepto práctico el programador se verá considerablemente beneficiado a la hora de crear sus propios algoritmos para sus estructuras de datos iterables o con propiedad de recorrido o de enumeración.

1. ¿Qué es una Secuencia?

Para contextualizar y adaptar la definición encontrada en [2] con C#, podemos definir a una secuencia como un conjunto de elementos (tipo de dato de la biblioteca base de clases o cualquiera tipo definido por el propio programador) reproducibles en serie. Esta definición guarda una estrecha relación con un iterador (cfr. Sintaxis y Semántica de un Iterador), debido a que es este último se encarga de invocar las funciones (métodos, indizadores, propiedades, &c.) que generan cada uno de los elementos de la secuencia en una determinada estructura de datos o generador de elementos de una serie (e.g., sucesión o secuencia Fibonacci).

2. Implementación de una Secuencia en C#

Para comprender mejor el concepto de secuencia explicado en la sección anterior, procedamos a escribir un ejemplo en código fuente C#. En este ejemplo resaltaremos el uso de la interfaz genérica IEnumerable<T> [4] para la generación de números de la serie Fibonacci [5], y además por cada número de esta serie que se genere realizar la comprobación de número par. La idea es generar en la sólo aquellos números de la serie Fibonacci que sean números pares: 2, 8, etc.


En las líneas 18-33 declaramos el método GeneradorFibonacci que se encarga de generar la serie hasta la cantidad especificada por su parámetro cantidadSerie. Por cada iteración del ciclo for (líneas 23-32) se genera un valor de la serie. Cada uno de estos valores retornados se pasan al método GeneradorNumeroPares (líneas 37-47). Este último método se encargará de enumerar cada elemento, siempre y cuando pase la prueba en la sentencia if de la línea 41, a la sección del método Main (líneas 8-14) para su posterior presentación en la salida estándar.

Podemos realizar una paráfrasis gráfica de la sucesión de eventos descritos en el párrafo anterior sobre el diagrama de eventos representado en la Figura 1.
Flujo de ejecución de la generación de una secuencia
Figura 1. Flujo de ejecución de la generación de una secuencia.

El Consumidor actúa sobre el método Main, dado que es el que invoca al método GeneradorNumeroPares, y este último del mismo modo invoca al método GeneradorFibonacci.

Compilación:


  1. csc /target:exe FibonacciPares.cs


Ejecución assembly:

  1. .\FibonacciPares.exe


> Prueba de ejecución (local):
Ejecución assembly FibonacciPares.exe
Figura 2. Ejecución assembly FibonacciPares.exe.

3. Conclusiones

La generación o composición de secuencias nos puede resultar de enorme utilidad cuando queremos generar una enumeración de elementos de una estructura de datos: lista simple, lista doblemente enlazada, vector, por ejemplo. En el ejemplo de la sección 2 aprendimos que el uso de la interfaz genérica IEnumerable<T> comprende un elemento de programa de importante utilidad, además de proveer flexibilidad, para la composición de secuencias y su respectiva enumeración de elementos. En el siguiente artículo C# estudiáremos los tipos nulos y sus propiedades.

4. Glosario

  • Algoritmo
  • Estructura de dato
  • Interfaz
  • Lista
  • Secuencia
  • Vector

5. Literatura & Enlaces

[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]: secuencia - significado de secuencia diccionario - http://es.thefreedictionary.com/secuencia
[3]: Sintaxis y Semántica de un Iterador en C# | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/08/sintaxis-y-semantica-de-un-iteradore-en-csharp.html
[4]: IEnumerable(T) Interface (System.Collections.Generic) - http://msdn.microsoft.com/en-us/library/9eekhta0%28v=vs.110%29.aspx
[5]: Sucesión de Fibonacci - Wikipedia, la enciclopedia libre - http://es.wikipedia.org/wiki/Sucesi%C3%B3n_de_Fibonacci


J

viernes, 29 de agosto de 2014

XML con C# (C1A4): Analizadores (Parsers) de Documentos XML

Índice

0. Introducción
1. ¿Qué es un Analizador XML?
2. Categorías de los Analizadores
2.1 DOM (Document Object Model)
2.2 SAX (Simple API for XML)
2.3 Otras clasificaciones
3. Conclusiones
4. Glosario
5. Literatura & Enlaces

0. Introducción

A lo largo de este artículo de XML con C# vamos a conocer los esenciales acerca de uno de los componentes para la manipulación, escritura y lectura de documentos XML: los analizadores. Comprenderemos que estas piezas de software son fundamentales cuando se trata de analizar un documento XML para crear significado sobre los datos representados en la estructura del documento; y partir de esta operación crear conocimiento útil para un contexto de aplicación en particular.

1. ¿Qué es un Analizador XML?

Un analizador de un documento XML, también conocido por el término anglosajón parser, es una pieza de software que se encarga de leer, escribir y manipular los elementos que comprenden la estructura de todo el documento XML. Esta tarea va a permitir crear significado sobre el contenido del documento, además de extraer información para crear conocimiento útil para el contexto de la aplicación que estemos construyendo.


Por otro lado, un sinónimo para referirnos a este componente es el de procesador. Como su nombre lo indica, y para parafrasear el párrafo anterior, un procesador se encarga (valga el pleonasmo) de procesar las piezas (elementos) de información representados como una estructura de árbol propia de este lenguaje de marcado extensible (cfr. ¿Qué es XML?).


En la siguiente sección trataremos las dos categorías a nivel de procesamiento de un analizador XML:
  • Analizadores basados en DOM, y
  • Analizadores basados en SAX.

2. Categorías de los Analizadores

2.1 DOM (Document Object Model)

DOM [2] es una convención multiplataforma y de independencia de lenguaje para la manipulación (lectura, escritura) de un documento XML. Estas características han sido el producto de la estandarización dirigida por la organización de estándares abiertos W3C. DOM es el tipo de procesador o analizador de documentos más común y popular hoy en día. Esto se debe principalmente a:
  • Representación arbórea de su estructura
  • Constante evolución (cfr. [2])
  • Simplicidad de manipulación
  • Validación eficiente del documento XML
Para resaltar su representación arbórea observemos la Figura 1:
Estructura arbórea de un documento XML
Figura 1. Estructura arbórea de un documento XML.
Esta estructura arbórea invertida es útil para el análisis del documento. El analizador (parser) basado en DOM empieza carga toda esta estructura en memoria para las consiguientes tareas de manipulación, escritura, y lectura. Aquí hay que resaltar que el hecho de cargar en memoria todo el contenido de un documento XML puede representar poco viable a nivel de eficiencia cuando se trata de enormes cantidades de datos y se cuenta con una relativa baja disponibilidad de memoria de trabajo. Frente a este aspecto el programador debe ser un muy cuidadoso al dimensionar el o los servidores o máquinas clientes para este análisis.

Sin embargo, esto también puede representar una ganancia a la propiedad de acceso aleatorio del contenido del árbol: el programador puede dirigirse a cualquier área específica del documento sin estar atado a una única dirección de lectura (i.e., arriba-abajo).


Por otro lado, Microsoft cuenta con una implementación propia de este analizador DOM:
Parser DOM de Microsoft
Figura 2. Parser DOM de Microsoft [1].

2.2 SAX (Simple API for XML)

Otro de los analizadores (procesadores, o parsers) de documentos XML disponible es SAX [3]. A diferencia de su homólogo, DOM, SAX no carga todo el contenido del documento en memoria principal (o de trabajo), en su lugar realiza un análisis unidireccional (arriba-abajo) según vayan ocurriendo eventos (de ahí que también se le conozca analizador orientado a eventos).

Continuando, cuando el programador ha especificado un elemento de interés sobre el documento XML, el analizador SAX disparará un evento que puede ser manipulado por el programador para llevar a cabo una tarea específica. La manipulación sólo está restringida a la lectura. Esto se debe a su modelo de acceso: secuencial.

A lo dicho anteriormente, es decir, frente a la limitación de solo lectura del documento XML, esta idea también puede representar una ventaja cuando se trata de analizar un documento con una ingente cantidad de información, que en el caso de usar un analizador DOM podría eventualmente generarse problemas en el rendimiento a la escasez de memoria de trabajo [1].


Igualmente, Microsoft también cuenta con un componente disponible para este tipo de analizador:
Parser SAX de Microsoft
Figura 3. Parser SAX de Microsoft [1].

2.3 Otras clasificaciones

Los analizadores o procesadores de documentos XML también se pueden clasificar a nivel de validación como:
  • Analizadores de validación
  • Analizadores de no-validación
En el caso de los primeros (i.e., analizadores de validación) la operación de validación se lleva a cabo contrastando el documento XML frente una Definición de Tipo de Documento (DTD) o un esquema (cfrValidación de Documentos XML con Esquemas y Definición de Tipo de Documentos); propiedad de la que carecen los analizadores de no-validación.


En lo que respecta a la infraestructura de .NET Framework, este cuenta con lenguaje de consulta estructurado LINQ [5], el cual posee con un conjunto de extensiones para ofrecer los mecanismos necesarios para la lectura y escritura de documentos XML. Esto queda anotado en [1]:
LINQ de Microsoft .NET Framework
Figura 3. LINQ de Microsoft .NET Framework [1].

3. Conclusiones

Nos ha quedado claro que los procesadores, parsers, o analizadores comprenden un componente o artefacto de software para crear significado de los elementos integrales de un documento XML. Reconocimos que existen dos implementaciones comunes y populares de este tipo de analizadores: DOM y SAX. El primero orientado al acceso aleatorio para la manipulación, lectura y escritura de documentos XML; el segundo, con capacidades para el manejo de documentos XML con un ingente cantidad de datos y, además, orientado a eventos. Al final vimos otras tipologías de analizadores: con validación y sin validación. En el próximo artículo hablaremos acerca de la resolución de problemas de representación e intercambio de datos: XSLT.

4. Glosario

  • Acceso aleatorio
  • Acceso secuencial
  • Analizador
  • Documento
  • DOM
  • DTD
  • Esqumea
  • Evento
  • LINQ
  • Memoria de trabajo
  • Memoria principal
  • Orientado a eventos
  • Parser
  • SAX
  • XML

5. Literatura & Enlaces

[1]: Beginning XML with C# 2008 From Novice to Professional by Bipin Joshi. Copyright 2008 Bipin Joshi, 978-1-4302-0998-0.
[2]: Document Object Model - Wikipedia, the free encyclopedia - https://en.wikipedia.org/wiki/Document_Object_Model
[3]:  XML con C# (C1A1): ¿Qué es XML? | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/08/xml-con-csharp-c1a1-que-es-xml.html
[4]: XML con C# (C1A3): Validación de Documentos XML con Esquemas y Definición de Tipo de Documentos | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/08/xml-con-csharp-c1a3-validacion-de-documentos-xml-con-esquemas-y-definicion-de-tipo-de-documentos.html
[5]: LINQ (Language-Integrated Query) - http://msdn.microsoft.com/en-us/library/bb397926.aspx


A

jueves, 28 de agosto de 2014

Receta Multithreading en C# No. 1-11: Manejo de Excepciones en Threads

Índice

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
4. Práctica: C#
5. Conclusiones
6. Glosario
7. Literatura & Enlaces

0. Introducción

En el estudio de esta receta multithreading comprenderemos el proceso de manejo de excepciones de threads en ejecución. Comprenderemos que esta tarea compromete sólo el manejo de las excepciones al interior del método adyacente al thread. En el ejemplo de la sección práctica simularemos la generación de una excepción que no cuenta con el correspondiente bloque try-catch, y otro método en donde el control de la excepción se lleva a cabo correctamente. Veremos que sucede con ambas situaciones.

1. Problema

Estudiar el manejo de las excepciones generadas en el interior de la implementación de un proceso asociado o adyacente a un thread.

2. Solución

En el cuerpo de la implementación de un método, como tradicionalmente lo hacemos, podemos especificar código de manejo de excepciones con las construcciones sintácticas C# diseñadas para este cometido: try-catch-finally.

3. Discusión de la Solución

En artículos C# ya hemos tratado en cierto grado de profundidad el manejo de excepciones. Aquí están los enlaces a los cinco artículos integrales de esta serie de excepciones:
[Nota: Hago la inclusión de estos enlaces para evitar extendernos en esta tema de las excepciones que en el contexto de esta receta se da por entendido.]

Por otro lado, y en particular, vale hacer mención de algunos aspectos importantes y cruciales en el manejo de excepciones con threads en ejecución. El primero de ellos es la advertencia encontrada en [1]:
«...It is very important to always place a try-catch block inside the thread because it is not possible to catch an exception outside a thread's code.»
Básicamente, lo anterior se puede resumir en que una excepción generada por un thread debe ser manipulada en el cuerpo de implementación del propio método adyacente, de lo contrario resulta imposible su manejo (como ya veremos en el ejemplo de la sección 4).

También hay que mencionar aquellas excepciones no manejables generadas, por ejemplo, con la suspensión de la ejecución de un thread (cfr. Abortar un Thread en Ejecución) o por la descarga de un dominio de aplicación [7]
  • ThreadAbortException [9]: Esta excepción es lanzada cuando se aborta la ejecución de un thread.
  • AppDomainUnloadedException [10]: Esta excepción se genera sobre un thread que ha intentado descargar un dominio de excepción (cfr. Creación de un Dominio de Aplicación).
Además como agregan en [7]:
«If any of these exceptions are unhandled in threads created by the common language runtime, the exception terminates the thread, but the common language runtime does not allow the exception to proceed further.»

4. Práctica: Código C#

En el siguiente ejemplo trataremos una excepción generada desde un método que se ejecuta sobre un thread independiente. Inclusive, demostraremos la generación de una excepción en el interior de un thread que no cuenta con un bloque de manejo excepciones try-catch para ver y distinguir su efecto ante la carencia de esta construcción sintáctica.

En las líneas 39-44 declaramos el método ThreadSinBloqueTryCatch. Este método genera una excepción tipo Exception, pero debemos resaltar que como se mencionó en la sección 3, es requisito indispensable que el cuerpo de implementación de un método adyacente a un thread cuenta con su propio bloque try-catch. Más adelante, líneas 47-61, se define el método ThreadConBloqueTryCatch, que a diferencia del método anterior, este sí cuenta con un bloque try-catch para manejar las excepciones que su lógica de implementación pudieran generar en el propio thread.


Continuando, en el punto de entrada de ejecución, Main, (líneas 8-35) se crea un primer thread de ejemplo para demostrar las capacidades de manejo de excepción interna del método ThreadConBloqueTryCatch: líneas 15, 18, y 21. Por el contrario, la operación de ejecución del thread t2 (línea 29) genera un error fatal en la aplicación que conlleva a su terminación abrupta. Esto se debe a la carencia del bloque try-catch del método ThreadSinBloqueTryCatch.

Compilación:


  1. csc /target:exe ManejoExcepcionesThread.cs

Ejecución assembly:


  1. .\ManejoExcepcionesThread.exe

> Prueba de ejecución (ideone.com).

> Prueba de ejecución (local):
Ejecución assembly ManejoExcepcionesThread.exe
Figura 1. Ejecución assembly ManejoExcepcionesThread.exe.

5. Conclusiones

Trabajamos en la práctica para la comprensión del manejo de excepciones en threads, tema de alta importancia debido a que su entendimiento nos permite construir aplicaciones multithreading tolerante a fallas lo que conlleva a la construcción de software más robusto y de nivel de diseño industrial. Con esta receta terminamos la serie de recetas dedicadas a los temas esenciales de threads en C#; para la próxima serie (capítulo 2) nos concentraremos en la sincronización de threads a lo largo de 9 entregas de este tipo.

6. Glosario

  • CLR
  • Descarga
  • Dominio de aplicación
  • Excepción
  • Exception
  • Multithreading
  • Sincronización
  • Thread
  • Tolerante a fallas

7. Literatura & Enlaces

[1]: Multithreading in C# 5.0 Cookbook by Eugene Agafonov. Copyright 2013 Eugene Agafonov, 978-1-84969-764-4.
[2]: Excepciones en C# - Parte 1: Introducción a las Excepciones | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/06/excepciones-en-csharp-parte-1-introduccion-a-las-excepciones.html
[3]: OrtizOL - Experiencias Construcción Software (xCSw): Excepciones en C# - Parte 2: Uso de Excepciones - http://ortizol.blogspot.com/2014/07/excepciones-en-csharp-parte-2-uso-de-excepciones.html
[4]: Excepciones en C# - Parte 3: Diseño de Excepciones Personalizadas | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/07/excepciones-en-csharp-parte-3-diseno-de-excepciones-personalizadas.html
[5]: Excepciones en C# - Parte 4: Propiedades de la Clase Base System.Exception | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/07/excepciones-en-csharp-parte-4-propiedades-de-la-clase-base-system.exception.html
[6]: Excepciones en C# - Parte 5: Ejemplos de Excepciones Comunes | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/07/excepciones-en-csharp-parte-5-ejemplos-de-excepciones-comunes.html
[7]: Exceptions in Managed Threads - http://msdn.microsoft.com/en-us/library/ms228965(v=vs.110).aspx
[8]: Receta Multithreading en C# No. 1-4: Abortar un Thread en Ejecución | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/06/receta-multithreading-en-csharp-no-1-4-abortar-un-thread-en-ejecucion.html
[9]: ThreadAbortException Class (System.Threading) - http://msdn.microsoft.com/en-us/library/system.threading.threadabortexception(v=vs.110).aspx
[10]: AppDomainUnloadedException Class (System) - http://msdn.microsoft.com/en-us/library/system.appdomainunloadedexception(v=vs.110).aspx
[11]: Receta No. 3-1 en C#: Creación de un Dominio de Aplicación (Application Domain) | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/05/receta-no-3-1-en-c-creacion-de-un.html


J