Mostrando entradas con la etiqueta source code. Mostrar todas las entradas
Mostrando entradas con la etiqueta source code. Mostrar todas las entradas

domingo, 19 de noviembre de 2017

Diccionarios en C# - Parte 1/6: IDictionary(TKey, TValue)

Índice

1. Introducción
2. Palabras Clave
3. La Interfaz IDictionary<TKey, TValue>
4. Ejemplo de Uso
5. Conclusiones
6. Literatura & Enlaces

1. Introducción

Entramos al estudio de los diccionarios: una estructura de datos o colección donde los elementos se representan con dos partes: una llave y un valor. Facilita la búsqueda, y es apropiada para listas ordenadas. En esta serie comprenderemos las interfaces que provee .NET para los diccionarios: IDictionary y IDictionary(TKey, TValue). También se incluye la descripción de implementaciones: OrderedDictionary, HybridDictionary y ListDictionary.


Este primer artículo describe la interfaz IDictionary(TKey, TValue), la cual constituye la interfaz para colecciones genéricas basadas en una llave y un valor.

2. Palabras Clave

  • Diccionario
  • Estructura de Datos
  • Llave
  • Valor

3. Diccionario


En el mundo de las colecciones o estructuras de datos un diccionario dispone los elementos por una llave y un valor asociado a esa llave. Para acceder a un elemento basta con especificar su llave; luego, la llave se puede ver como la palabra en un diccionario enciclopédico y su valor como su definición.
Analogía con diccionario enciclopédico
Figura 1. Analogía con diccionario enciclopédico ("Imagen diccionario", 2017).

Entre las características distintivas de esta estructura se hallan (Albahari, 2012)
  • Los datos o contenido de un elemento se acceden a través de un valor único.
  • El acceso tiene un complejidad O(1).
  • Una de la llave es través de un algoritmo de hash.
  • La estructura se análoga a un mapa: dado un nombre se accede a la locación concreta donde se haya el elemento.
  • Es posible tener como llave un valor null.
  • Se puede especificar un enumerador pero sin la promesa que el contenido esté ordenado.
En C# existen diferentes implementaciones de diccionario: la primera que se va a estudiar es IDictionary<TKey, TValue>.

3. La Interfaz IDictionary<TKey, TValue>

Esta interfaz representa un diccionario con llave y valor genéricos: TKey, TValue. En la firma de encabezado de esta interfaz se aprecia que implementa la interfaz genérica ICollection<KeyValuePair<TKey, TValue>>; y así mismo la adaptación a estructura enumerable con IEnumerable<KeyValuePair<TKey, TValue>>.

Entre sus propiedades genéricas se hallan ("IDictionary", 2017)
  • Count: Obtiene el número de elementos en el diccionario; i.e., la cantidad de llaves.
  • Keys: Llaves del diccionario.
  • Values: Valores del diccionario.
Y así mismo, estos métodos ("IDictionary", 2017):
  • Add(T): Agrega un elemento al diccionario.
  • Add(TKey, TValue): Agrega un elemento a partir de una llave y un valor.
  • Contains(T): Comprueba si un elemento existe en la colección.
  • Remove(T): Remueve la primera ocurrencia.
  • Remove(TKey): Remueve un elemento a través de su llave.
Para el método Add vale apuntar que si se intenta agregar un elemento con la misma llave, la excepción ArgumentException (Excepciones en C# - Parte 5: Ejemplos de Excepciones Comunes) es lanzada.

Para la enumeración de los elementos se provee el método GetEnumerator. Este método retorna una secuencia de objetos KeyValuePair: representa la llave y el valor de cada uno de los elementos que contiene el diccionario.

4. Ejemplo de Uso

Veamos el siguiente ejemplo de uso básico:

En la línea 10 se crea una instancia de la implementación concreta de IDictionary<TKey, TValue>. Esta instancia representa la asociación de extensiones de tipos de archivos con el programa manejador para apertura: en las líneas 13-16 se agregan los elementos, y luego, en las líneas 18-22 se itera el diccionario: notemos aquí que cada elemento se presenta con un objeto KeyValuePair<string, string>.

5. Conclusiones

Describimos la interfaz IDictionary<TKey, TValue>: representación general o abstracta de una estructura de datos basada en diccionario: cada elemento se presenta por dos ítems: una llave y un valor. Su analogía principal es la de Dictionary<TKey, TValue>.

6. Literatura & Enlaces

Albahari, J., Albahari, B. (2012). C# 5.0 in a Nutshell. United States: O'Reilly Media.

Imagen diccionario (2017). Recuperado desde: https://androidayuda.com/app/uploads/2015/02/diccionario-2.jpg
IDictionary(TKey, TValue) Interface (System.Collections.Generic) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/s4ys34ea(v=vs.110).aspx
Excepciones en C# - Parte 5: Ejemplos de Excepciones Comunes (2017). Recuperado desde: https://ortizol.blogspot.com.co/2014/07/excepciones-en-csharp-parte-5-ejemplos-de-excepciones-comunes.html


O

lunes, 6 de noviembre de 2017

Listas, Colas, Pilas y Conjuntos en C# - Parte 6/6: HashSet(T) y SortedSet(T)

Índice

1. Introducción
2. Palabras Clave
3. Clase Genérica HashSet<T>
4. Clase Genérica SortedSet<T>
5. Conclusiones
6. Literatura & Enlaces

1. Introducción

Cada nueva versión mayor de .NET Framework trae consigo cambios sobresalientes: entre ellos se puede contar la adición de dos elementos de programa: HastSet<T> y SortedSet<T>. Estas dos clases genéricas son colecciones que resaltan por métodos de búsqueda basado en hash, no permiten la agregación de elementos duplicados, y no cuenta con acceso basado en índice o posición. Este último artículo de la serie Listas, Colas, Pilas y Conjuntos en C# describe, grosso modo, estas dos interesantes clases, exponiendos sus características importantes.

2. Palabras Clave

  • .NET Framework
  • Clase
  • Colección
  • Genéricos
  • Hash

3. Clase Genérica HashSet<T>

La clase genérica HashSet<T> almacena los elementos sin un orden particular, y su implementación consiste en llaves almacenadas en una estructura hashtable (o tabla de hash); estas llaves representan el identificador unívoco para acceder a los de la tabla.

Cuenta con la implementación de la interfaz genérica ICollection<T>: en consecuencia, posee con métodos de acceso y mutación como Contains, Add y Remove.

¿Pero qué hace interesante esta clase? De acuerdo con "HashSet(T) Class" (2017), esta clase cuenta con operaciones de conjuntos de alto rendimiento. Por ejemplo, se pueden mencionar los métodos:
  • UnionWith(IEnumerable<T>): lleva a cabo la operación de conjuntos unión de elementos de dos colecciones.
  • InsersectWith(IEnumerable<T>): realiza la operación de conjuntos intersección para generar el conjunto de elementos comunes a dos colecciones.
  • ExceptWith(IEnumerable<T>): ejecuta la operación de substracción.
Estos métodos y otros son de naturaleza destructiva (Albahari, 2012); esto quiere decir que, por ejemplo, la operación de IntersectWith modifica la estructura removiendo los elementos que no son comunes entre ambos conjuntos.

Veamos este ejemplo de uso:

El resultado de ejecución de este programa es:


Contenido conjunto números pares:
2 4 6 8 10 
Contenido conjunto números impares:
1 3 5 7 9 
Conjunto resultante de la unión de pares e impares:
2 4 6 8 10 1 3 5 7 9 
En ideone.com se puede probar online la ejecución del código: https://ideone.com/nvubPq

4. Clase Genérica SortedSet<T>

Esta es otra clase alto desempeño orientada a almacenar información como un conjunto: donde los elementos no se repiten. A diferencia de HashSet<T>, SortedSet<T> almacena los elementos de forma ordenada.

Internamente esta clase está implementada usando un árbol rojo-negro ("Árbol rojo-negro", 2017)Al igual que HashSet<T>, SortedSet>T> implementa la interfaz genérica IEnumerable<T> para la enumeración de elementos de la colección (Enumeración e Interfaces IEnumerator(T) e IEnumerable(T) en C# (2017)).

Supongamos que creamos el siguiente código de ejemplo:

SortedSet<char> dostoevsky = new SortedSet<char>("dostoevsky");

Al iterar este objeto 

foreach(char c in dostoevsky)
{
    Console.Write(c);
}

se obtienen los siguientes caracteres ordenados alfabéticamente:

dekostvy

El constructor de esta clase acepta como argumento un objeto IComparar<T> que sirva como especificador de método de comparación (Albahari, 2012).

5. Conclusiones

Se exploraron dos clases nuevas para el almacenamiento y manipulación de elementos de teoría de conjuntos. El uso apropiado de estas clases para proyectos de software que requieran tratar datos con operaciones de teoría de conjuntos puede eventualmente dar como resultado software eficiente gracias al alto rendimiento de estas estructuras.

La siguiente serie de artículos  tratará acerca de estructuras de datos basadas en diccionarios.

6. Literatura & Enlaces

Albahari, J., Albahari, B. (2012). C# 5.0 in a Nutshell. United States: O'Reilly Media.
HashSet(T) Class (System.Collections.Generic) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/bb359438%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
SortedSet(T) Class (System.Collections.Generic) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/dd412070%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
Árbol rojo-negro - Wikipedia, la enciclopedia libre (2017). Recuperado desde: https://es.wikipedia.org/wiki/%C3%81rbol_rojo-negro
Enumeración e Interfaces IEnumerator(T) e IEnumerable(T) en C# (2017). Recuperado desde: https://ortizol.blogspot.com.co/2017/08/enumeracion-e-interfaces-ienumerator-t-e-ienumerable-t-en-csharp.html


O

domingo, 29 de octubre de 2017

Listas, Colas, Pilas y Conjuntos en C# - Parte 5/6: BitArray

Índice

1. Introducción
2. Palabras Clave
3. La Clase BitArray
4. Conclusiones
5. Literatura & Enlaces

1. Introducción

La razón de ser de la clase que estudia en este artículo destaca además por su crecimiento dinámico, pero su gestión eficiente en memoria de los valores booleanos: inclusive superior a un arreglo o una List genérica de elementos bool.

2. Palabras Clave

  • Arreglo
  • bool
  • Crecimiento dinámico
  • Eficiencia
  • Lista

3. La Clase BitArray

Internamente la clase BitArray usa un único bit por cada elemento del arreglo, en lugar de los ocho bits (byte) que cupa un elemento bool en una colección de tipo arreglo o List<T> (Albahari, 2012).

Lo anterior se traduce en eficiencia en almacenamiento.

Por otra parte, el crecimiento de esta clase está relacionado de forma directa con la adición o remoción de un elemento: la propiedad Length cambia de acuerdo al número de unidades agregadas o removidas.

Entre los métodos, por su parte, esenciales y particulares a esta clase se hallan:
  • And: lleva a cabo la operación bitwise (Operadores Bitwise (Bit a Bit) en C#) de y o conjugación lógica.
  • Or: realiza la operación bitwise de o inclusivo.
  • Xor: realiza la operación bitwise de o exclusivo.
  • Not: niega o invierte cada unos de los valores del arreglo de bits.
Los primeros tres métodos listados reciben como argumento un elemento BitArray: la operación lógica se lleva bit a bit en en el arreglo dado respecto al que invoca el método.

A continuación un ejemplo de uso básico:

4. Conclusiones

Se presentó el uso básico de la clase BitArray para la manipulación de elementos booleanos que ocupan un único bit en memoria: esto evidencia un alto nivel de eficiencia frente a otras soluciones como List<T> o un arreglo básico elementos bool.

El último artículo de esta serie comprenderá el estudio de las clases genéricas HashSet<T> y SortedSet<T>.

5. Literatura & Enlaces

Albahari, J., Albahari, B. (2012). C# 5.0 in a Nutshell. United States: O'Reilly Media.
BitArray Class (System.Collections) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.collections.bitarray%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
Operadores Bitwise (Bit a Bit) en C# (2017). Recuperado desde: https://ortizol.blogspot.com.co/2013/07/operadores-bitwise-bit-bit-en-c.html


O

domingo, 13 de agosto de 2017

Enumeración e Interfaces IEnumerator(T) e IEnumerable(T) en C#

Índice

1. Introducción
2. Palabras Clave
3. Interfaz IEnumerable<T>
4. Interfaz IEnumerator<T>
5. Implementación de Interfaces de Enumeración
6. Ejemplo de Uso
7. Conclusiones
8. Literatura & Enlaces

1. Introducción

En el artículo anterior se presentaron las versiones no-genéricas de las interfaces IEnumerable y IEnumerator; ahora, llega la oportunidad de estudiar la utilidad y uso de las versiones genéricas: IEnumerable<T> y IEnumerator<T>. El ejemplo de uso que se presentará al final del artículo pretendenrán ser lo más explícito posibles, sin embargo se mantendrá la simplicidad en el código.

2. Palabras Clave

  • Clase genérica
  • Colección
  • Estructura de datos
  • Interfaz

3. Interfaz IEnumerable<T>

La interfaz IEnumerable<T> ("IEnumerable(T)", 2017) proporciona a un tipo de dato que represente una colección la capacidad de recorrer sus elementos en modo lectura. Principalmente esta interfaz está diseñada para trabajar con genericidad: la estructura o colección será capaz de enumerar o listar los elementos independiente del tipo de dato particular especificado para el tipo paramétrico.

Pongamos como ejemplo la clase List<T> ("List(T) Class", 2017). Esta clase permite especificar un tipo de dato concreto a almacenar en la estructura; así:

List<Tipo> lista = new List<Tipo>();

El tipo paramétrico Tipo será el tipo de dato de los elementos que se almacenen en la variable lista.

Supongamos ahora que agregamos elementos a la lista:

lista.add(new Tipo(...));
lista.add(new Tipo(...));
lista.add(new Tipo(...));
//...
lista.add(new Tipo(...));

Para recorrer la lista el programador puede usar el ciclo foreach:

foreach(Tipo tipo in lista){
    // ...
}

En el cuerpo del ciclo foreach se puede llevar a cabo operaciones de solo lectura sobre la colección almacenada en lista:List<T>.

Otras clases de colecciones que implementan esta interfaz:
  • Dictionary<TKey, TValue>
  • Stack<T>

4. Interfaz IEnumerator<T>

A través de la interfaz IEnumerator<T> ("IEnumerator(T) Interface", 2017) permite implementar la iteración o enumeración de los elementos de una colección de tipos genéricos. Vale enunciar que esta interfaz genérica herada de IEnumerator (Enumeración e Interfaces IEnumerator e IEnumerable en C#); esto se observa en la siguiente figura:
Jerarquía de herencia de enumeadores genéricos
Figura 1. Jerarquía de herencia de enumeadores genéricos (Albahari, 2012).
Al igual que su contraparte no genérica, las colecciones que implementan esta interfaz tienen habilitada la iteración de sus elementos a través del ciclo foreach. C# lo que hace es ocultar los detalles de la iteración de los elementos a través de esta versión del loop for.

Continuando, IEnumerator<T> implementa la interfaz IDisposable, permitiendo al proceso de enumeración llevar control de referencias a recursos de conexión a datos, y asegurar que éstos liberen los recursos utilizados cuando hayan terminado su ejecución (Albahari, 2012). Cuando se usa el ciclo foreach como en 

foreach(Tipo tipo in lista){
    // ...
}

internamente se está llevando a cabo la siguiente equivalencia

using(var enumerador = lista.GetEnumerator()){
    while(enumerador.MoveNext()){
        // ...
    }
}

5. Implementación Intefaces de Enumeración

En Albahari (2012) se exponen motivacionees para implementar estas interfaces:
  • Soportar el ciclo foreach
  • Interoperar con elementos de programa que requieran de una colección estándar
  • Soportar inicializadores de colecciones
  • Cumplir los requerimientos de interfaces de colecciones más avanzadas

6. Ejemplo de Uso

El siguiente ejemplo de uso permite demostrar cómo crear una colección personalizada, llamada Lista, con un tipo paramétrico. El constructor de esta clase permite establecer el número de elementos que contendrá la colección; y además, contiene un método para agregar elementos: void AgregarElemento(T).

Este código se compila y se ejecuta de la siguiente manera:

csc /out:Coleccion.exe Coleccion.cs

./Coleccion.exe


El resultado de la ejecución:

Dostoevsky
Balzac
Dickens


El código se puede probar en:

http://ideone.com/PvBaTX

7. Conclusiones

Este artículo aprendimos a distinguir la utilidad esencial de las interfaces IEnumerator y IEnumerable en sus versiones genéricas. Notamos que proveen al programador los mecanismos generales para iterar una colección que acepta tipos paramétricos para almacenar en su estructura de datos. El ejemplo es presentando tuvo como objetivo dar un vistazo general sobre cómo implementar la interfaz IEnumerable<T>, y retornar un objeto IEnumerator<T>.

El próximo artículo lo dedicaremos a estudiar las interfaces ICollection y IList.

8. Literatura & Enlaces

Albahari, J., Albahari, B. (2012). C# 5.0 in a Nutshell. United States: O'Reilly Media.

A Beginner's Tutorial on Implementing IEnumerable Interface and Understanding yield Keyword - CodeProject (2017). Recuperado desde: https://www.codeproject.com/Articles/474678/A-Beginners-Tutorial-on-Implementing-IEnumerable-I
IEnumerable(T) Interface (System.Collections.Generic) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/9eekhta0%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
List(T) Class (System.Collections.Generic) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/6sh2ey19(v=vs.110).aspx
IEnumerator(T) Interface (System.Collections.Generic) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/78dfe2yb(v=vs.110).aspx
Enumeración e Interfaces IEnumerator e IEnumerable en C# (2017). Recuperado desde: https://ortizol.blogspot.com/2017/08/enumeracion-e-interfaces-ienumerator-e-ienumerable-en-csharp.html


J

jueves, 10 de agosto de 2017

Enumeración e Interfaces IEnumerator e IEnumerable en C#

Índice

1. Introducción
2. Palabras Clave
3. Interfaz IEnumerable
4. Interfaz IEnumerator
5. Clase String
6. Ejemplo de Uso: Listar Nombres
7. Conclusiones
8. Literatura & Enlaces

1. Introducción

En este artículo el programador C# aprenderá a distinguir la utilidad de dos interfaces fundamentales para implementar el recorrido de los elementos de una colección: IEnumerable y IEnumerator. Estas interfaces proveen los contratos de implementación que deben cumplir las estructuras de datos o colecciones para explorar su contenido a través del ciclo mejorado foreach.

2. Palabras Clave

  • Colección
  • Contrato
  • Enumeración
  • Estructura de datos
  • Interfaz

3. Interfaz IEnumerable

Este elemento de programa es una interfaz que expone un contrato de enumeración sobre colecciones o estructuras de datos no genéricas. En concreto, una colección debe escribir una implementación particular para el método GetEnumerator para devolver un elemento IEnumerator, el cual describe la lógica de recorrido.

Respecto a esta clase, hay que tener en cuenta la observación hallada en "IEnumerable Interface" (2017):
"It is a best practice to implement IEnumerable and IEnumerator on your collection classes to enable the foreach [...] syntax, however implementing IEnumerable is not required."
Esta consideración es importante a razón de que el programador puede omitir la implementación de IEnumerable y directamente utilizar la implementación de IEnumerator para hacer de una estructura de datos enumerable. Toda la lógica de recorrido se puede escribir en un tipo de dato que implemente esta última interfaz.

Sin embargo, en (Albahari, 2012) se considera a IEnumerable como un proveedor de enumeración o "IEnumeratorProvider". Lo que facilita exponer la lógica de recorrido en una clase/archivo independiente, pero sobretodo permite a diferentes secciones o locaciones de código hacer el recorrido de la colección sin interferir una con otra.

4. Interfaz IEnumerator

IEnumerator es un contrato o interfaz que dicta a un tipo de dato los métodos y propiedades que debe implementar para facilitar el recorrido de los elementos contenidos en la colección.

Los miembros que se deben implementar son los siguientes:
  • Propiedades:
    • Current: retorna el elemento de la posición actual de la colección.
  • Métodos:
    • MoveNext: mueve el índice a la siguiente posición de la colección.
    • Reset: posiciona el índice antes del primer elemento de la colección.
Al igual que la interfaz IEnumerable, IEnumerator está orientado para tipos de datos no genéricos. Para tipos de datos genéricos, el namespace System.Collections.Generic define las interfaces análogas IEnumerable<T>IEnumerator<T>.


En la Figura 1 (Albahari, 2012) se ilustra un esquema visual sobre la estructuración de estos tipos en .NET Framework:
Esquema de interfaces para colecciones
Figura 1. Esquema de interfaces para colecciones.

5. String

La clase String (namespace System) implementa la interfaz IEnumerable para enumerar cada uno de sus elementos: los caracteres que la integran:
Definición clase String
Figura 2. Definición clase String ("String Class", 2017).

Nótese en la imagen como esta clase implementa las versiones no-genéricas y genéricas de estas interfaces. En el próximo artículo se presenta la versión genérica de este tipo de protocolo o interfaz.

6. Ejemplo de Uso

El siguiente ejemplo de uso comprende 4 archivos de código fuente C# que demuestra cómo implementar las clases IEnumerable y IEnumerator para enumerar los elementos de una colección que contiene entidades Persona:
  • Persona.cs: Contiene la definición de la entidad que representa una persona con su nombre y apellido.
  • Gente.cs: Implementa la interfaz IEnumerable para retornar un objeto GenteEnumerator.
  • GenteEnumerator.cs: Implementa la interfaz IEnumerator con la lógica necesaria para desplazarse por cada uno de los elementos de la clase Persona.
  • App.cs: Código cliente que pone a prueba la enumeración de elementos de una colección de objetos Persona.
Archivo Gente.cs [enlace alternativo]:

Archivo GenteEnumerator.cs [enlace alternativo]:

Archivo App.cs [enlace alternativo]:

Para compilar este código basta con ejecutar el siguiente comando a través del compilador de C#:

csc /out:App.exe *.cs

La ejecución se lleva a cabo con:

./App.exe

El resultado de ejecutar esta aplicación es:

Fyodor Dostoevsky
Honoré Balzac

Charles Dickens

7. Conclusiones

Se presentaron las interfaz IEnumerable y IEnumerator. Se describió su utilidad para enumerar elementos de una colección o estructura de datos. Estas interfaces son protocolos estándar definidos en .NET Framework que permiten al programador C# sacar máximo provecho de los elementos estándar del lenguaje: el ciclo foreach.

En el siguiente artículo se explorarán las versiones análagas en genéricos de estas dos interfaces: IEnumerable<T> y IEnumerator<T>.

8. Literatura & Enlaces

Albahari, J., Albahari, B. (2012). C# 5.0 in a Nutshell. United States: O'Reilly Media.
IEnumerable Interface (System.Collections) (2017). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.collections.ienumerable(v=vs.110).aspx
String Class (System) (2017). Recuperado desde:
https://msdn.microsoft.com/en-us/library/system.string(v=vs.110).aspx


O