Sie sind auf Seite 1von 87

Índice.

Unidad I: Repaso. 5
Definificiones. 5
Modificadores de Acceso. 6
Referencia .this. 6
Garbage Collector y Finalizers (Destructors). 7
Miembros estáticos. 7
Composición y Agregación. 8
Cardinalidad. 8
Colección ArrayList. 9
Bibliografía. 11

Unidad II: Herencia. 11


Miembros Protegidos. 12
Constructores. 12
Clase Object. 13
Sobreescritura de métodos en clases derivadas. 14
Representación UML. 14
Bibliografía. 15

Unidad III: Polimorfismo e interfaces. 15


Polimorfismo. 15
Conversión descendente (downcasting) 15
Implementación en código. 15
Operador is y comprobación de tipos. 16
Interfaz. 16
Declaración de una interfaz. 16
Representación UML. 17
Interfaces comunes en la Librería de Clases de .NET 17
Clases abstractas. 18
Métodos y propiedades abstractos. 18
Ejemplo de clases y métodos abstractos. 19
Clases y métodos sealed. 19
Bibliografía. 19

Unidad IV: Manejo de excepciones. 20


Definiciones. 20
Manejo de Excepciones. 21
La Jerarquía de .NET Exception y Librería .NET. 22
Propiedades de la clase Exception. 22
Clases Exception definidas por el usuario. 23
Creación excepciones. 23
Excepciones Comunes. 24
Bibliografía. 26

Unidad V: String. 26
Definiciones. 26
Clase String. 27
Clase StringBuilder. 32
Búsquedas en un Objeto StringBuilder. 34
Struct Char. 35
Clase Regex. 37
Bibliografía. 37

Unidad VI: Archivos. 37


Jerarquía de datos. 37
Archivos y Streams (Flujos). 39
Clase File. 39
Enumeraciones. 39
Métodos. 41
Ejemplo: Uso de método para verificar la existencia de un archivo. 42
Clase Directory. 43
Métodos. 43
Ejemplo: Obtener todos los archivos de un directorio y moverlos a otra localización. 44
Ejemplo: Mover un directorio y todo su contenido a otro directorio. 44
Clase FileStream. 45
Constructores. 45
Propiedades. 45
Ejemplo: uso de constructores. 46
Clase StreamReader. 48
Constructores. 48
Métodos. 48
Ejemplo: uso de StreamReader para lectura de un archivo. 49
Clase StreamWriter. 49
Constructores. 49
Métodos. 50
Ejemplo: uso de StreamWriter para escritura en archivo. 51
Ejemplo de Lectura/Escritura de Archivos. 51
Serialización. 51
Proceso de Serialización. 52
Conversión de un objeto en serializable. 52
Serialización de un objeto. 52
Básica y binaria. 52
Personalizada. 53
Ejemplo: Serialización/Deserialización Básica Binaria. 53
Ventanas modales: OpenFileDialog y SaveFileDialog. 55
Clases OpenFileDialog y SaveFileDialog. 55
Propiedades Comunes. 55
Métodos Comunes. 56
Ejemplo: uso de OpenFileDialog. 56
Ejemplo: uso de SaveFileDialog 57
Bibliografía. 57

Unidad VII: Estructuras de Datos. 58


Valores Struct Simples o Primitivos. 58
Conversión Boxing/Unboxing. 58
Clases Autorreferenciales. 59
LinkedList. 59
Implementación. 60
Clase ListNode 60
Clase List. 60
Clase EmptyListException. 64
Listas simple y doblemente enlazadas, lineales y circulares. 65
Stacks (Pilas). 65
Implementación. 65
Queues (Colas). 67
Implementación. 67
Árboles. 68
Árboles Binarios. 68
Búsqueda en árboles de búsqueda binarios. 68
Algoritmos de búsqueda para árboles binarios de enteros. 69
Algoritmo de recorrido InOrder. 69
Algoritmo de recorrido PreOrder. 69
Algoritmo de recorrido PostOrder. 69
Bibliografía. 70

Unidad VIII: Colecciones y Genéricos. 70


Algunas Clases Collections en el Framework .NET. 71
Clase Array. 73
Propiedades. 73
Métodos. 73
Colecciones No Genéricas. 73
Clase ArrayList. 73
Clase Stack. 74
Propiedades. 74
Métodos. 74
Clase Queue. 74
Propiedades. 74
Métodos. 75
Genéricos. 75
Colecciones Genéricas. 75
Clase LinkedList <T>. 75
Propiedades. 76
Métodos. 76
Clase List<T>. 76
Propiedades. 76
Métodos. 77
Bibliografía. 78
Unidad I: Repaso.

Definificiones.
Clase: ​una clase o struct es como un plano o molde que especifica lo que el tipo puede hacer. Un
tipo definido como una clase es un tipo “referencia”. En tiempo de ejecución una variable de tipo
referencia contiene el valor null hasta que explícitamente se cree una instancia de la clase
empleando el operador new o se asigne un objeto de tipo compatible que haya sido creado
previamente.

Objeto: ​instancia de una clase. Bloque de memoria que ha sido alocada y configurada acorde a
su clase. Un programa puede crear varios objetos de la misma clase, estos pueden ser
almacenados en una variable de referencia o en un arreglo o colección.

Método:​ bloque de código que contiene una serie de sentencias. un programa causa que estas
sentencias sean ejecutadas al llamar al método especificando los argumentos requeridos por el
mismo. Los métodos son declarados en una clase o struct especificado el valor de retorno, el
nombre del método, los parámetros del método, el nivel de acceso:
● public
● private
● protected
y modificadores opcionales tales como:
● abstract
● sealed
La forma en la que se declara un método se denomina firma. ​El valor de retorno de un método
no es parte de la firma para permitir la sobrecarga; sin embargo, es parte de la firma al
determinar la compatibilidad entre un delegado y el método al cual apunta.
Los parámetros de los métodos se encuentran entre los paréntesis y se encuentran separados por
comas. Paréntesis vacíos indican que el método no requiere parámetros.

Constructor:​ es un método cuyo nombre es el mismo que el nombre de su tipo. Su firma incluye
solo el nombre del método y su lista de parámetros; no incluye un valor de retorno. Este método
es llamado cuando una clase o struct es creado. Una clase o struct puede tener múltiples
constructores que tomen diferentes argumentos (deben variar en cantidad, tipo u orden para que
puedan ser distinguidos en tiempo de ejecución). Los constructores permiten setear los valores
por defecto (estado inicial del objeto), limitar la instanciación y escribir código que sea flexible y
fácil de leer. Si no se especifica un constructor, C# genera uno por defecto (implícito) que
instancia el objeto y setea sus variables miembros a los valores por defecto preestablecidos del
lenguaje (​ver Tabla de valores por defecto​)
Modificadores de Acceso.
permiten especificar los niveles de accesibilidad declarada para miembros (clases, propiedades,
métodos).
● public:​ el acceso no se encuentra restringido.
● private:​ el acceso se encuentra limitado al tipo que lo contiene.
● protected:​ el acceso se encuentra limitado a la clase contenedora o a tipos derivados de
dicha clase contenedora.
● internal:​ el acceso se encuentra limitado al ensamblado actual.
● protected internal:​ el acceso está limitado al ensamblado actual o al los tipos derivados
de la clase contenedora.
● private protected:​ el acceso está limitado a la clase contenedora o a los tipos derivados
de la clase contenedora que hay en el ensamblado actual (a partir de versión 7.2)
Solo se permite un modificador de acceso para un miembro o tipo, excepto cuando se usan las
combinaciones protected internal o private protected. No se permiten modificadores de acceso en
espacios de nombres, dado que los espacios de nombre no tienen restricciones de acceso. Los
modificadores de acceso no se permiten en espacios de nombre (namespaces) ya que estos no
tienen restricciones de acceso.

Referencia .this.
La palabra reservada​ ​this​ refiere a la instancia actual de la clase y es también usada como un
modificador del primer parámetro de un método de extensión.Sus usos mas comunes son:
● Para calificar a miembros ocultos por nombres similares

​ ublic class ​Employee


p
{
​private string​ alias;
​private string​ name;

​public​ Employee(​string​ name, ​string ​alias)


{
​// Use this to qualify the members of the class
// instead of the constructor parameters.
​this​.name = name;
​this​.alias = alias;
}
}

● Para pasar un objeto como un parámetro a otros métodos

CalcTax(​this​);

● Para declarar indexadores


public int this​[​int​ param]
{
​get ​{ ​return ​array[param]; }
​set ​{ array[param] = ​value​; }
}

Garbage Collector y Finalizers (Destructors).


Cada objeto creado emplea varios recursos del sistema, tales como memoria. En muchos
lenguajes de programación, estos recursos se reservan para el uso del objeto hasta que son
explícitamente liberados por el programador. Si todas las referencias al objeto que manejan los
recursos se perdieran antes de que dichos recursos sean explícitamente liberados, la aplicación
no podría acceder a los recursos para liberarlos y se produciría una fuga de recursos.
en C#, el CLR (Common Language Runtime) realiza un manejo automático de la memoria
empleando un Garbage Collector (GC) que “reclama” la memoria ocupada por objetos que no se
encuentran en uso, de modo tal que esa memoria puede ser usada para otros objetos. Cuando no
hay más referencias para un objeto, este se vuelve elegible para su destrucción. Cada objeto tiene
un miembro especial llamado destructor (Finalizer), que es invocado por el GC para realizar una
limpieza de terminación a un objeto antes de que el recolector de basura reclame la memoria que
se le había asignado a este. Un destructor se declara como un constructor sin parámetros,excepto
que su nombre es el mismo que el de su clase precedido por un tilde (~), y no tiene modificadores
de acceso en su encabezado; en los diagramas UML se representan con el nombre de la clase y
el estereotipo <<destructor>>. Luego de que el GC llama al destructor del objeto este se vuelve
elegible para su “recolección”.
La clase estática GC contiene los métodos:
● Collect():​ fuerza una recolección inmediata de todas las generaciones.
● WaitForPendingFinalizers():​ suspende los hilos actuales hasta que el hilo que se
encuentra procesando la cola de finalizadores haya vaciado dicha cola.
que pueden ser empleados para liberar recursos específicos en algún momento dado.

Un problema con el GC es que no garantiza que realizará la tarea en un tiempo especificado. Por
tanto, el GC puede llamar al destructor del objeto en cualquier momento luego de que este se
haya vuelto elegible para la destrucción y reclamar su memoria en cualquier momento posterior a
la ejecución del finalizador. No es claro cuando el destructor será llamado y por esta razón los
destructores son raramente empleados.

Miembros estáticos.
Una clase no estática puede contener métodos, campos, propiedades o eventos estáticos. El
miembro estático puede ser llamado en una clase o incluso cuando ninguna instancia de la clase
ha sido creada. El miembro estático siempre se accede empleando el nombre de la clase y no el
de la instancia. Solo una copia del miembro estático existe y es compartida por todas las
instancias de la clase. Métodos y propiedades estáticos no pueden acceder a campos no estáticos
o eventos en su tipo contenedor, y no pueden acceder a una variable de instancia de cualquier
objeto a menos que sean explícitamente pasados como parámetro de un método.
Dos usos comunes de campos o atributos estáticos son llevar la cuenta del número de objetos
instanciados o almacenar algún valor que deba compartirse por todas las instancias.
Los métodos estáticos pueden sobrecargarse pero no sobreescribirse, dado que pertenecen a la
clase y no a alguna de las instancias de dicha clase.
C# no soporta variables locales estáticas.
Los miembros estáticos se declaran empleando la palabra reservada ​static.​

Composición y Agregación.

● Composición (Def.):​ Representa una relación “tiene un”, en donde el ciclo de vida del
todo y las partes se encuentra ligados. Solo una clase puede representar el todo y las
partes pueden pertenecer a un solo “todo” al mismo tiempo.
En este modelo en particular se considera que la creación de las partes se realiza desde el
constructor del todo.

Representación UML.
Se representa con una línea con un rombo relleno en uno de sus extremos, el cual indica
la clase que representa el todo.

● Agregación (Def.): ​Representa una relación “tiene un”, en forma débil. El ciclo de vida de
las partes y el todo no se encuentra ligados, por tanto las partes pueden existir sin un todo
y el todo sin las partes. El todo no es responsable de la creación y destrucción de las
partes. Una parte puede pertenecer a más de un todo al mismo tiempo. Las partes se
asocian al todo a través de variables de instancia.

Representación UML.
Se representa con una línea con un rombo vacío en uno de sus extremos, el cual indica la
clase que representa el todo.

→ ​(Sin referencias comprobables)​ En los diagramas UML de ambas relaciones, si el extremo


perteneciente a la parte presenta una flecha esto indica que solo la clase que representa al todo
contiene referencias a los objetos de la clase parte; mientras que la ausencia de la flecha implica
bidireccionalidad: el todo contiene referencias de los objetos de la parte y la parte contiene
referencias de la clase que representa al todo.

Cardinalidad.

Simbología Descripción Estructura (implementación)

1 Uno Variable de referencia


m Un valor entero (fijo) Arreglo de m elementos

0..1 Cero o uno Variable de referencia (null si


es 0)

m, n m ó n con n > m Vector de n elementos

m..n Como mínimo m y como Vector de n elementos


máximo n

* o 0..* Cualquier cantidad, a partir de Vector dinámico (ArrayList,


cero cualquier cantidad. List <T>, etc)

1.. * Uno o más. Vector dinámico.

La cantidad de objetos que se crearán de cada clase en ambas relaciones está dada por la
cardinalidad, la cual se indica en cada extremo de la relación correspondiente a cada clase en el
diagrama UML. La implementación de algunas de esas cardinalidades requiere el empleo de
algunas estructuras de datos (tales como arreglos) que se incluyen en las clases.

Colección ArrayList.
Estructura dinámica de datos que puede aumentar o disminuir la cantidad de memoria requerida
para almacenar datos en respuesta a cambios en los requerimientos de una aplicación durante el
tiempo de ejecución. Pertenece a las colecciones no genéricas, por tanto almacena referencias a
objetos de tipo object y deben realizarse conversiones (casteos) para trabajar con propiedades o
métodos específicos de cada tipo de objeto que se almacene. Pueden almacenarse objetos de
cualquier tipo, ya que todos derivan de la clase ​Object​.
Clase ArrayList: ​pertenece al namespace​ System.Collections ​y representa un arreglo dinámico
cuyo tamaño puede modificarse a través de los métodos de la clase. Implementa la interfaz ​IList​.

Propiedad Descripción

Capacity obtiene y establece el número de elementos


para los cuales el espacio de memoria se
encuentra reservado en el ArrayList

Count Propiedad de solo lectura que obtiene el


número de elementos alojados en el arreglo
(int)

Método Descripción

Add() Agrega un objeto al final del arreglo y devuelve


un int especificando el índice al cual el objeto
fue adicionado.

Clear() Remueve todos los elementos del arreglo

Contains() Devuelve true si el objeto especificado como


argumento se encuentra en el arreglo, en otro
caso devuelve false.

IndexOf() Devuelve el índice de la primera ocurrencia del


objeto especificado como argumento en el
arreglo.

Insert() Inserta un objeto en el índice especificado


como argumento.

Remove() Elimina la primera ocurrencia del objeto,


especificado como argumento del arreglo.

RemoveAt() Remueve del arreglo el objeto que se


encuentre en el índice especificado como
argumento.

RemoveRange() Elimina un número especificado de elementos


comenzando desde el índice explicitado como
argumento del método

Sort() Ordena el arreglo (los elementos deben


implementar IComparable o la versión
sobrecargada de este método que recibe
IComparer debe ser implementada)

TrimToSize() Establece la capacidad del arreglo al número


de elementos que este contenga actualmente.

Por defecto, un objeto de esta clase puede almacenar tantos elementos como el valor indicado en
la propiedad Capacity. Cuando esta capacidad inicial se supera, automáticamente se alojan los
recursos necesarios para duplicar la capacidad anterior. En general, el proceso de agregar
elementos es lento cuando es necesario asignar memoria (se supera la capacidad), pero es rápido
cuando la capacidad es suficiente.
Es posible ajustar el valor de la propiedad Capacity a la cantidad de objetos actualmente
contenidos en el arreglo mediante el método TrimToSize() para optimizar el uso de memoria, sin
embargo, si luego se deseara adicionar nuevos elementos, el proceso se volverá lento dado que
la ArrayList debe crecer dinámicamente.
Los métodos IndexOf(), Contains() y Remove() realizan una ​búsqueda lineal​ para cumplir sus
funciones, una operación costosa cuando el vector es grande. Si la ArrayList está ordenada se
puede emplear el método ​BinarySearch(Array, Object)​ para realizar una búsqueda más eficiente
en el caso de los dos primeros métodos antes mencionados, este devuelve el índice del elemento
especificado si este se encuentra en el arreglo o un número negativo si este no se encuentra.
Bibliografía.
● https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/cla
sses
● https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/obj
ects
● https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/met
hods
● https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/accessibility-l
evels
● https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/con
structors
● https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/this
● https://docs.microsoft.com/en-us/dotnet/api/system.gc?view=netframework-4.7.2
● https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/des
tructors
● https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/stat
ic-classes-and-static-class-members
● https://docs.microsoft.com/en-us/dotnet/api/system.collections.arraylist?view=netframework
-4.7.2
● Deitel & Deitel. “How to Program: Visual C# 2012. 5th Edition”. Chapter 4, 10 and 21
p. 821-825.

Unidad II: Herencia.


La herencia es una forma de reutilización de software en el que una clase nueva es creada al
absorber miembros preexistentes de otra clase y potenciarlos con nuevas capacidades o
capacidades modificadas. La clase existente de la cual la nueva clase hereda miembros se
denomina la clase base y la nueva clase se denomina clase derivada. Cada clase derivada puede
convertirse en clase base para otras clases derivadas, siendo al mismo tiempo clase base y
derivada. La herencia ​es una relación de “es un”​, en donde un objeto de la clase derivada
puede también ser tratado como un objeto de su clase base.
Una clase derivada exhibe el comportamiento de su clase base y agrega sus propios campos y
métodos particulares, por lo que es más específica que su clase base, que tiende a ser más
general, y representa a un grupo más especializado de objetos.
La clase base directa es la clase base de la cual la clase derivada explícitamente hereda. Una
clase base indirecta constituye cualquiera que se encuentre por sobre la clase base directa en la
jerarquía que define las relaciones de herencia entre las clases.
Solo se soporta herencia simple en C#.
Una clase derivada puede personalizar los métodos que hereda de su clase base. En tales casos,
la clase derivada puede sobrescribir (​override​) el método de la clase base con su implementación
apropiada. Para ello, los métodos de la clase base deben ser explícitamente ​declarados​ ​virtuales
si se desea sobreescribirlos en la clase derivada.

Miembros Protegidos.
Los miembros privados de una clase base son heredados a sus clases derivadas pero no son
directamente accesibles para los métodos y propiedades de la clase derivada. Empleando el
modificador de acceso​ protected​ se obtiene un nivel de acceso intermedio entre ​public​ y​ private​,
haciendo que los miembros de la clase base protegidos puedan ser accedidos directamente solo
por los miembros de esa clase base y por todos los miembros de las clases derivadas.
Todos los miembros no privados mantienen su modificador de acceso original cuando se
convierten en miembros de la clase derivada. Los métodos de las clases derivadas pueden
referirse a miembros públicos o protegidos heredados de la clase base simplemente usando el
nombre de los miembros. Cuando se sobreescribe un método de la clase base, la versión del
método en la clase base puede accederse empleando ​base.​ (palabra reservada base seguida del
operador de acceso a miembros “.”) seguido del nombre del método.

Problemas con las variables de instancia protected.


1. La clase derivada puede asignar valores inválidos a la variable, ya que puede setear el
valor de la variable heredada directamente sin emplear propiedades (set; get).
2. Los métodos de la clase derivada son más propensos a ser escritos con dependencia de la
implementación de los datos en la clase base. En la práctica, las clases derivadas
deberían depender únicamente de los servicios de la clase base (métodos y propiedades
no privados), por lo que se evitaría tener que realizar modificaciones en todas las clases
derivadas si la implementación de la clase derivada cambia.

Declarar variables de instancia con el modificador de acceso private, proveyendo


propiedades públicas para manipularlas y validarlas ayuda a mantener un buen desarrollo
de software.

Constructores.
El constructor de la clase derivada llama de manera explícita o implícita al constructor de la clase
base para asegurar que las variables de instancia heredadas de la clase base sean inicializadas
apropiadamente:
● Explícita:​ empleando el inicializador del constructor con la palabra reservada base
seguida de los parámetros que posea el constructor de la clase base (deben coincidir el
número y el tipo de parámetros).
● Implícita:​ Sin invocarlo, directamente se crea la instancia del objeto de la clase derivada
empleando el constructor predeterminado sin parámetros de la clase base, si este lo tiene.
La llamada es realizada por el compilador. Incluso si una clase no tiene constructor, el
constructor por defecto que el compilador implícitamente declarará para la clase llamará al
constructor por defecto de la clase base. La clase Object es la única clase que no tiene
clase base.
Si la clase base es derivada de otra, ​esta llamará al constructor de su clase base directa para
la creación de dicha instancia​. Esta cadena de llamadas de constructores finaliza en la creación
de una instancia de Object de la cual derivan todas las clases de C#. Cada constructor antes de
realizar sus tareas invoca al constructor de su clase base directa, de esta manera el constructor
de la clase derivada es el último en ejecutarse de la cadena.

Clase Object.
Todas las clases heredan directa o indirectamente de esta clase. Sus 7 métodos son heredados
por todas las clases.

Método Descripción

Equals() Compara dos objetos por igualdad y devuelve


true si son iguales y false si no los son. Toma
cualquier objeto como argumento. Cuando un
objeto de cualquier clase debe ser comparado
por igualdad, la clase debe sobreescribir el
método Equals() para comparar el contenido
de los objetos.

Finalize() Este método no puede ser declarado


explícitamente o llamado. Cuando una clase
contiene un destructor, el compilador
implícitamente lo renombra para sobreescribir
el método protected Finalize, el cual es
llamado solo por el recolector de basura antes
de que éste reclame la memoria asignada a
dicho objeto. El GC no garantiza que
reclamará a un objeto, por tanto no hay
garantías de que el método se ejecutará.
Cuando este método se ejecuta en un clase
base, realiza su tarea y luego invoca el
método Finalize de la clase base. Debe
evitarse usar este método.

GetHashCode() Una estructura de datos Hashtable relaciona


objetos (keys) con otros objetos (values).
Cuando un valor es inicialmente insertado en
una Hashtable, el método GetHashCode() de
la key es llamado.El valor retornado es usado
por la Hashtable para determinar la locación
en la cual insertar el valor correspondiente. El
hashcode de la key se emplea también para
insertar el value correspondiente a dicha key.
GetType() Cada objeto conoce su tipo en tiempo de
ejecución. Este método devuelve un objeto de
la clase Type (namespace System) que
contiene información acerca del tipo del
objeto, tal como el nombre de su clase
(propiedad FullName de Type).

MemberwiseClone() Este método protected, que no toma


argumentos y devuelve una referencia a
object, hace una copia de el objeto en el cual
es llamado. La implementación de este
método hace una copia superficial-valores de
variables de instancia en un objeto son
copiadas en otro objeto del mismo tipo. Para
tipos de referencia, solo las referencias son
copiadas.

ReferenceEquals() Este método estático recibe dos referencias de


object y devuelve true si son de la misma
instancia o si son referencias null. Sino
devuelve false.

ToString() Devuelve una representación string de un


objeto. La implementación por defecto de este
método devuelve el espacio de nombre
seguido por un punto y el nombre de la clase
del objeto. Puede sobreescribirse para
especificar una representación de string
apropiada del objeto.

Sobreescritura de métodos en clases derivadas.


Para sobreescribir un método de la clase base, el método en esta debe marcarse explícitamente
como ​virtual​, ​abstract​ (los métodos abstractos son implícitamente virtuales) u ​override ​(si es una
clase derivada de otra que sobrescribe dicho método, lo declara implícitamente virtual para sus
clases derivadas en la jerarquía). La clase derivada debe declarar el método con la palabra
reservada ​override ​y con la misma firma y tipo de retorno que el de la clase base.
Los métodos virtuales permiten trabajar con grupos de objetos relacionados de forma uniforme.

Representación UML.
La herencia se representa con una línea conteniendo una flecha vacía en uno de sus extremos,
que indica cuál es la clase base. El extremo que no tiene la flecha señala la clase derivada. Puede
haber múltiples clases derivadas, pero solo una clase base (una clase no puede heredar de dos
clases bases al mismo tiempo).
El modificador de acceso ​protected​ se representa en antecediendo a los miembros de la clase
base con el símbolo #.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ​EjemploHerencia
{
​ //Implementación de una interfaz en la clase base. Clase
Abstracta
public abstract class​ ​Prisma​:​IComparable
{
private double ​altura;

public double ​Altura


{
get
{
return ​altura;
}
set
{
altura = value;
}
}
public​ ​Prisma​(​double​ altura)
{
this​.altura = altura;
}

public abstract double​ GetVolumen();

public abstract string​ GetFormaBase();

public override string​ ToString()


{
return ​"Prisma: "​ + GetFormaBase() + ​" - Volumen: "​ +
GetVolumen().ToString();
}

public int​ CompareTo(​object​ obj)


{
Prisma ​prisma = obj ​as ​Prisma​;
return this​.GetVolumen().CompareTo(prisma.GetVolumen());
}
}
}

namespace EjemploHerencia
{
//Implementación de Herencia en clase concreta.
class​ ​Circulo​:​Prisma
{
private double​ radio;

public double​ Radio


{
get
{
return ​radio;
}
set
{
radio = ​value​;
}
}

​ irculo​(​double​ altura, ​double ​radio)


public​ C
: b ​ ase​(altura)
{
this​.radio = radio;
}

public double​ GetArea()


{
return​ ​Math.Round​(2 * Math.PI * radio * Altura, 2);
}

public override double​ GetVolumen()


{
return​ ​Math.Round​(​Math.PI​ * ​Math.Pow​(radio, 2) * Altura);
}

public override string​ GetFormaBase()


{
return​ ​"Base Circular"​;
}

public override string​ ToString()


{
return base​.ToString() + " - Area: " +
GetArea().ToString();
}
}
}

Bibliografía.
● Deitel & Deitel. “How to Program: Visual C# 2012. 5th Edition”. Chapter 11.

Unidad III: Polimorfismo e interfaces.

Polimorfismo.
Considerado el tercer pilar de la Programación Orientada a Objetos, junto con la Herencia y la
Encapsulación. Posee dos aspectos distintivos:
● En tiempo de ejecución, los objetos de una clase derivada pueden ser tratados como
objetos de una clase base como parámetros de métodos y colecciones o arreglos. Cuando
esto ocurre, el tipo del objeto declarado no es idéntico a su tipo durante la ejecución.
● Las clases bases pueden definir e implementar métodos virtuales y las clases derivadas
pueden sobreescribirlos, proveyendo su propia definición e implementación. En tiempo de
ejecución, cuando el código del cliente llama al método, el CLR busca el tipo del objeto en
ejecución, e invoca el método sobreescrito. Por tanto, en el código fuente puede llamarse a
un método de la clase base y producir la ejecución de la versión del método de la clase
derivada.

Conversión descendente (downcasting)


Técnica que se realiza cuando, empleando polimorfismo, se quiere acceder a métodos específicos
de la clase derivada. En estos casos, se requiere realizar un casteo de la referencia de la clase
base a una referencia de la clase derivada para poder acceder a los métodos específicos de dicha
clase.

Implementación en código.
Implica el uso de referencias de la clase base para la instanciación de objetos de la clase
derivada. Al momento de instanciar se emplea el constructor de la clase derivada en la referencia
del objeto de la clase base, de modo tal que este sea tratado como un objeto de la clase base y
todos los objetos sean procesados conjuntamente de forma común. Si se requiere emplear algún
método específico de la clase derivada se emplea ​downcasting​.

public partial class F ​ orm1 : Form


{
ArrayList ​lista​ = new ​ArrayList​()​;
//Referencia de la clase base
Prisma​ ​prisma;

public ​Form1()
{
InitializeComponent();
rbtnCirculo.Checked =​ false​;
rbtnRectangulo.Checked =​ false​;
}

private void ​btnCargar_Click(object sender, EventArgs e)


{
if ​(ValidarDatos())
{
if ​(rbtnCirculo.Checked)
{
​//Instanciacion de la clase derivada
prisma = ​new
Circulo​(Convert.ToDouble(tbAltura.Text),
Convert.ToDouble(tbRadio.Text));
lista.Add(prisma);
LimpiarCampos();
}
if ​(rbtnRectangulo.Checked)
{
​//Instanciacion de la clase derivada
prisma = ​new
​Rectangulo​(Convert.ToDouble(tbAltura.Text),
Convert.ToDouble(tbLadoBase.Text),
Convert.ToDouble(tbLadoAltura.Text));
lista.Add(prisma);
LimpiarCampos();
}

}
else
{
MessageBox.Show("Complete los campos
correspondientes");
}
}

Operador is y comprobación de tipos.


El operador ​is​ puede emplearse para conocer el tipo de un objeto (clase derivada), cuando este
se ha instanciado usando una referencia a la clase base, previo a usar ​downcasting​. Este
operador comprueba si el objeto es de un tipo dado, devuelve true en caso de coincidencia o false
en caso contrario.

if​ (unaPersona ​is​ ​Alumno​)


{
}
else if​( unaPersona ​is ​Docente​)
{
}
Interfaz.
Describe un set de métodos, eventos, indexadores y/o propiedades que pueden ser llamados en
un objeto pero que no provee implementaciones concretas para ellos. Se pueden declarar clases
que implementan una o más interfaces. Todos y cada uno de los miembros de la interfaz debe ser
definido para todas las clases que la implementen; en la clase, los miembros implementados de la
interfaz deben ser públicos, no-estáticos y deben tener la misma firma que en la interfaz. Una vez
que una clase implementa una interfaz, todos los objetos de esa clase tienen una relación de
herencia (“es un”) con el tipo de la interface.
Las interfaces son particularmente útiles para asignar funcionalidades comunes a clases
posiblemente no relacionadas. Esto permite que los objetos de clases no relacionadas puedan ser
procesados polimórficamente- clases que implementan la misma interfaz pueden responder a la
mismas llamadas a los métodos.

Declaración de una interfaz.


La implementación de una interfaz en una clase se realiza del siguiente modo:

public abstract class​ ​Prisma​:​IComparable


{

public int​ CompareTo(​object​ obj)


{
Prisma ​prisma = obj ​as ​Prisma​;
return this​.GetVolumen().CompareTo(prisma.GetVolumen());
}
}

Se pueden implementar varias interfaces, listandolas seguidas de la clase separadas por comas.
Si dicha clase hereda de otra, las interfaces a implementar se listan luego de de esta separadas
por una coma.
El usuario puede generar sus propias interfaces declarando su nombre antecedido por la letra “I”.
Los métodos dicha interfaz deben ser declarados eligiendo un nombre que represente de forma
general su aplicación.

Representación UML.
La interfaz se distingue de una clase mediante el uso del decorador <<interface>> sobre el
nombre de la misma. ​La relación entre la clase y la interface es la de realización o
compresión (realization)​; una clase comprende o implementa una interface. En el modelo esto
es indicado por una línea punteada con una flecha hueca que apunta a la clase que implementa la
interface.

Interfaces comunes en la Librería de Clases de .NET

Interface Descripción

IComparable Contiene varios operadores de comparación


(<, <=, >, >=, ==, !=) que permiten comparar
valores de tipos simples. Estos operadores
pueden ser empleados para comparar dos
objetos. La interface puede ser usada también
para permitir a dos objetos de una clase que la
implementen ser comparados entre sí.
Contiene un método CompareTo(), que
compara al objeto que llama al método con el
objeto pasado como argumento a este y
devuelve un valor (int) indicando si el objeto es
menos que/menor (negativo), igual a (cero) o
mas que/mayor (positivo)que el objeto pasado
como argumento,empleando un criterio
especificado por el programador. La interfaz
es comúnmente empleada para el
ordenamiento de elementos en arreglos.

IComponent Implementado por cualquier clase que


represente un componente, incluyendo
controles GUI (botones, labels, etc). Define los
comportamientos que los componentes deben
implementar.

IDisposable Implementada por clases que deben proveer


un mecanismo explícito para liberar los
recursos. Algunos recursos pueden ser
utilizados por solo un programa a la vez.
Adicionalmente, algunos recursos,tales como
archivos en discos, son recursos no
manejados que, contrario a la memoria, no
pueden ser liberados por el GC. Las clases
que implementan esta interfaz proveen de un
método Dispose() que puede ser llamado
explícitamente para liberar recursos.

IEnumerator Usada para iterar a través de elementos de


una colección (arreglos) de a uno por vez.
Contiene el método MoveNext() que permite
moverse de un elemento al siguiente en la
colección, el método Reset() para mover a la
posición anterior al primer elemento y la
propiedad Current para devolver el objeto en
la locación actual.

Clases abstractas.
Son clases de las cuales nunca se desea instanciar un objeto o que carecen de implementación,
ya que se encuentran “incompletas”, y son empleadas como clases base en jerarquías de
herencia. Su propósito es proveer de una clase base apropiada de las que otras clases puedan
heredar y por tanto compartir un diseño común.
Las clases abstractas tienen las siguientes características:
● No pueden ser instanciadas.
● Pueden contener accesores o métodos abstractos.
● No es posible modificar una clase abstracta ( modificador ​abstract​) con el modificador
sealed​ ​ya que ambos modificadores tienen un significado opuesto: el modificador ​sealed
impide que la clase pueda ser heredada mientras que el modificador ​abstract​ ​requiere que
la clase sea heredada.
● Una clase no abstracta (concreta) derivada de una clase abstracta debe contener
implementaciones de todos los métodos y accesores abstractos heredados.

Métodos y propiedades abstractos.


Son aquellos que contienen el modificador ​abstract ​en su declaración. Los métodos abstractos
poseen las siguientes características:
● Son implícitamente virtuales.
● Su declaración (como abstracto) sólo es permitida en clases abstractas.
● Como su declaración no provee implementación, no hay cuerpo del método y su
declaración termina con un ​‘;’​ y no contiene ‘{}’ seguido de la firma.
La implementación se provee por la sobreescritura del método (​override​), la cual es un miembro
de una clase no abstracta. Es un error emplear los modificadores ​static ​y ​virtual​ ​en la declaración
de un método abstracto.

Las propiedades abstractas se comportan como los métodos excepto por la diferencia en la
sintaxis de declaración e invocación. Es un error usar el modificador ​abstract​ ​en una propiedad
estática. Una propiedad abstracta heredada puede ser sobreescrita incluyendo una declaración de
la propiedad que use el modificador ​override​.

Un constructor no puede ser declarado abstracto, ya que los constructores no se heredan y


por tanto no podrían ser implementados.

Ejemplo de clases y métodos abstractos.


(Ver Ejemplos de UML y Código en Herencia y Polimorfismo).

Clases y métodos sealed.


Un método declarado ​sealed ​en una clase no puede ser sobreescrito en una clase derivada. Los
métodos declarados privados o estáticos son implícitamente ​sealed​, porque es imposible
sobreescribirlos en la clase derivada. Un método de una clase derivada declarado ​sealed ​y
override ​puede sobreescribir un método de la clase base pero no puede ser sobreescrito en
clases derivadas de esta mas abajo en la jerarquía.
La declaración de un método ​sealed ​no puede cambiar, por lo que todas las clases derivadas
usan la misma implementación y la llamadas a métodos ​sealed ​se resuelven en tiempo de
compilación - esto es conocido como unión estática (​static binding​).

Una clase declarada ​sealed ​no puede ser una clase base. Todos los métodos de una clase
sealed ​son implícitamente ​sealed​. Ej: ​Clase String​.

Bibliografía.
● https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/
● https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/pol
ymorphism
● https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/abstract
● https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/sealed
● Deitel & Deitel. “How to Program: Visual C# 2012. 5th Edition”. Chapter 12.
Unidad IV: Manejo de excepciones.

Definiciones.
Excepción:​ Indicador de que un problema ha ocurrido durante la ejecución de un programa.
Suelen ser infrecuentes.

El manejo de excepciones permite crear programas que controlen las excepciones, permitiendo
● Que el programa continúe la ejecución.
● Notificar al usuario del problema antes de terminar la ejecución de forma controlada, en
casos en los que esta no pueda continuar su ejecución normal.
● Garantizar que recursos empleados por un programa sean liberados posteriormente,
incluso ante la ocurrencia de una excepción (bloque finally).

Cuando ocurre una excepción, el IDE muestra un cuadro de diálogo conteniendo la ​Stack Trace
(rastro de pila-de llamadas-): incluye el nombre de la clase a la que pertenece la excepción, en un
mensaje indicando el problema que ocurrió y el camino que lleva a la excepción, método a
método.
Ejemplo:
● Excepción: ​DivideByZeroException​.

Unhandled Exception:System.DivideByZeroException: 
Attempted to divide by zero. 
at DivideByZeroExceptionHandling.Main() 
in C:\examples\ch13\Fig13_01\DivideByZeroNoExceptionHandling\ 
DivideByZeroNoExceptionHandling\ 
DivideByZeroNoExceptionHandling.cs:line 18 
En el mensaje de error se puede observar el nombre de la clase de la excepción
(​System.DivideByZeroException​) seguido de un texto que indica porque la misma tuvo lugar. En
la stack trace (​Ver detalles​), cada “at” indica una línea de código en el método en particular que
se estaba ejecutando cuando ocurrió la excepción, la dirección y el nombre del archivo
conteniendo el código y el número de línea en donde ocurrió la excepción. El primer “at” en la
línea de la stack trace indica el ​throw point​ de la excepción- el punto inicial al cual la excepción
ocurrió.

Manejo de Excepciones.
Se emplea la ​sentencia try​, la cual consiste en un ​bloque try​, uno o mas ​bloques catch​ y,
ocasionalmente, un ​bloque finally​. El código que puede producir la excepción se coloca en el
bloque try​ mientras que el código para el manejo de excepciones se encuentra en el ​bloque
catch​. Un bloque catch especifica un parámetro de excepción que representa la excepción que
dicho bloque puede manejar. Este puede usar el identificador del parámetro para interactuar con
un objeto de excepción que haya “atrapado”. Si no hay necesidad de emplear un objeto excepción
en el ​bloque catch​ este puede ser omitido. Opcionalmente, se puede incluir un ​bloque catch​ que
no especifique un tipo de excepción (conocido como ​catch general​) que maneje todos los tipos
de excepciones; este debe encontrarse siempre como último bloque catch, de usarse. Si el
bloque try​ termina debido a una excepción, el CLR busca el primer ​bloque catch​ cuyo tipo en su
parámetro coincida con el tipo de la excepción y lo ejecuta obviando el resto de los bloques catch.
Una coincidencia se da si el tipo del parámetro y el de la excepción coinciden o si el tipo de la
excepción es de una clase derivada de la del parámetro del bloque antes mencionado.
Luego de que cualquiera de los bloques catch termine, el programa continúa con la siguiente
sentencia que se encuentre luego del último bloque catch.
Al menos un bloque catch o finally debe seguir al bloque try. Adicionalmente, cuando el bloque try
finaliza, las variables locales definidas en dicho bloque pierden alcance por lo que no podrán ser
accedidas en otros bloques (tales como el bloque finally).

El ​bloque finally​ se emplea para código asociado a la liberación de recursos por parte del
programa o archivos que se estén empleando en él, ya que este se ejecuta independientemente
de si el bloque try logró ejecutarse (se ejecuta inmediatamente despues) o su ejecución se vio
interrumpida por una excepción (se ejecuta luego del bloque catch). Si una excepción no es
manejada por un bloque catch o si un bloque catch asociado al try lanza una excepción, este
bloque se ejecuta antes de que la excepción sea procesada por el siguiente bloque try. El bloque
finally es opcional.

Una excepción no manejada es aquella para la cual no hay un bloque catch coincidente.

Ejemplo:
using​ System;

class​ ​ExceptionTestClass
{
​public​ ​static​ ​void​ ​Main​()
{
​int​ x = 0;
​try
{
​int​ y = 100/x;
}
​catch​ (ArithmeticException e)
{
Console.WriteLine(​"ArithmeticException Handler: {0}"​,
e.ToString());
}
​catch​ (Exception e)
{
Console.WriteLine(​"Generic Exception Handler: {0}"​,
e.ToString());
}
}
}
/*
This code example produces the following results:

ArithmeticException Handler: System.DivideByZeroException: Attempted to


divide by zero.
at ExceptionTestClass.Main()

*/

La Jerarquía de .NET Exception y Librería .NET.


En C#, el mecanismo de manejo de excepciones permite que solo los objetos de la clase
Exception ​(​namespace System​) y sus clases derivadas puedan ser lanzados y atrapados como
excepciones. La clase ​Exception​ (​namespace System​) es la clase base de la jerarquía de .NET
Exception y ellas derivan dos clases principales:

● SystemException: ​representa las excepciones que tienen que ver con el entorno de
ejecución. En general, son excepciones graves de las que no se puede volver (invocar un
método de una variable de referencia que no referencia a un objeto, invocar a un método
recursivo que llena la pila).

● ApplicationException:​ representa las excepciones que se pueden producir en una


aplicación durante su ejecución y sirve como clase base para el desarrollo de clases
derivadas que representen excepciones específicas de la aplicación (excepciones
definidas por usuario).
Propiedades de la clase Exception.
● Message:​ almacena una string con el mensaje de error asociado al objeto Exception. Este
mensaje puede ser el asociado por defecto al tipo de la excepción o un mensaje
personalizado pasado al constructor de un objeto Exception cuando este es lanzado.
● StackTrace:​ contiene un string con la pila de llamadas a métodos. Representa una serie
de métodos que no se han terminado de procesar al momento de la ocurrencia de la
excepción. Puede también incluir los números de línea, siendo el primero aquel
correspondiente al ​throw point​ y los subsiguientes indicando los lugares desde los cuales
los métodos en la stack trace fueron llamados, si dicha información es accesible para el
IDE.
● InnerException (readOnly): ​devuelve un objeto que describe el error que causó la
excepción. El valor de esta propiedad es pasado en el constructor o es nulo si no fue
previsto en el constructor. Se emplea para dar mas información acerca de excepciones
específicas que puedan ser creadas por el programador. ​Ej:​ En un sistema de
contabilidad, el programador podría generar una excepción específica para su aplicación
tal como ​InvalidAccountNumberFormatException​, seteando como ​InnerException ​un
objeto de tipo FormatException que tendría la información de cómo y en donde se produjo
el error. La excepción creada por el programador indicaría el tipo de error específico (que
incluye el error de formato) pero sería la propiedad la que alojaría la información sobre el
error.
● HelpLink: ​especifica la localización del archivo de ayuda que describe el problema que
ocurrió, es null si dicho archivo no existe.
● Source: ​especifica el nombre de la aplicación u objeto que causó la excepción.
● TargetSite: ​especifica el método donde la excepción se originó.

Clases Exception definidas por el usuario.


Deben derivar directa e indirectamente de la clase ​Exception ​de ​namespace System​, tener un
nombre en su clase que termine con “Exception” y tener tres constructores:
● Constructor sin parámetros.
public​ ​Exception​ ()​;
● Constructor que reciba un string como argumento (mensaje de error).
public​ ​Exception​ (​string​ message)​;
● Constructor que reciba un string y un objeto de tipo Exception (InnerException) como
argumentos.
public​ ​Exception​ (​string​ message, ​Exception ​innerException)​;

Cuando se crea código que tira excepciones, este debe estar bien documentado para que otros
desarrolladores que usen el código puedan saber cómo manejarlas.
Creación excepciones.
Las excepciones se crean empleando la palabra reservada ​throw ​seguida de​ new​; las
excepciones pueden ser generadas por el CLR, el Framework .NET, cualquier librería de terceros
o por código en la aplicación​ ​. La ejecución de la sentencia ​throw​ indica que un problema ha
ocurrido en el código y específica un objeto a ser lanzado. El operando de la sentencia ​throw
puede ser de tipo Exception o de cualquiera de sus clases derivadas. El string pasado en el
constructor se convierte en el mensaje de error del objeto de tipo Exception.

Ejemplo:
class​ ​ExceptionTest
{
​static​ ​double​ ​SafeDivision​(​double​ x, ​double​ y)
{
​if​ (y == 0)
​throw​ ​new​ System.DivideByZeroException();
​return​ x / y;
}
​static​ ​void​ ​Main​()
{
​// Input for test purposes. Change the values to see
​// exception handling behavior.
​double​ a = 98, b = 0;
​double​ result = 0;

​ ry
t
{
result = SafeDivision(a, b);
Console.WriteLine(​"{0} divided by {1} = {2}"​, a, b, result);
}
​catch​ (DivideByZeroException e)
{
Console.WriteLine(​"Attempted divide by zero."​);
}
}
}

Las excepciones pueden ser re-lanzadas dentro del primer bloque catch que las atrape. Esto
indica que dicho bloque catch hizo un procesamiento parcial de la excepción y ahora la arroja
nuevamente para continuar su procesamiento. En general, se considera una mejor práctica el
lanzar una nueva excepción y pasar la original como argumento en el constructor de la nueva
excepción, la cual será el valor de la propiedad InnerException (​ver ejemplo en la descripción
de la propiedad​). Esto mantiene toda la información de la Stack Trace de la excepción original
que se perdería de lanzar nuevamente la misma excepción.
Excepciones Comunes.

Excepción Descripción

AccessException No acceder a un miembro de tipo, tal como un


método o campo.

ArgumentException Argumento de un método no válido

ArgumentNullException Cuando se pasa una referencia nula como


argumento a un método que no lo acepta
como argumento válido.

ArgumentOutOfRangeException El valor del argumento se encuentra fuera de


rango de valores definidos por el método
invocado (arreglos).

ArithmeticException Errores en operaciones aritméticas, casteos o


conversiones.

ArrayTypeMismatchException Cuando se desea alojar en un arreglo un


objeto de tipo incorrecto.

BadImageFormatException Cuando la imagen de una librería dinámica de


links (DLL) o un programa ejecutable son
inválidos.

CoreException Clase base para excepciones lanzadas por el


tiempo de ejecución.

DividebyZeroException Cuando se intenta dividir un número integrer o


decimal por cero.

FormatException Cuando el formato de un argumento es


inválido o cuando un formato compuesto de
string no está bien formado.

IndexOutOfRangeException Cuando se intenta acceder a un elemento en


un arreglo o colección con un índice que se
encuentra fuera de los límites del mismo.

InvalidCastException Cuando el casteo o la conversión explícita es


inválida.

InvalidOperationException Cuando la llamada de un método es inválida


para el estado actual del objeto.

MissingMemberException Cuando se intenta acceder dinámicamente a


un miembro de una clase que no existe o no
fue declarado como público.
NotFiniteNumberException Cuando un valor de punto flotante mas infinito,
menos infinito o NaN (Not-a-Number)

NullReferenceException Cuando se intenta referenciar al objeto de una


variable de referencia que es null.

OutOfMemoryException Cuando no hay suficiente memoria para


continuar la ejecución de un programa.

StackOverFlowException Cuando la pila de ejecución se “rebalsa”


porque contiene demasiadas llamadas a
métodos anidadas. Esta clase no puede ser
heredada.

SystemException verificación en tiempo de ejecución fallida.


Clase base para las SystemExceptions

Bibliografía.
● https://docs.microsoft.com/en-us/dotnet/api/system.exception?view=netframework-4.7.2#de
finition
● https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/exceptions/
● Deitel & Deitel. “How to Program: Visual C# 2012. 5th Edition”. Chapter 13.

Unidad V: String.

Definiciones.
Constantes de caracteres:​ es un carácter que se encuentra representado por un valor entero
denominado código de carácter (character code). Estas constantes se encuentran establecidas de
acuerdo con el set de caracteres Unicode, el cual contiene mayor cantidad de símbolos y letras
que el ASCII. Ej: el valor entero ‘122’ corresponde a la constante de caracter ‘z’.

String:​ es una serie de caracteres tratados como una unidad. Estos pueden ser letras
mayúsculas, letras minúsculas, dígitos y varios caracteres especiales tales como +, -, *, /, $, etc.
Un string es un objeto de la clase ​String ​en el ​namespace System​. Los literales de strings,
denominados constantes de string se escriben como una secuencia de caracteres entre comillas.
Ejemplo:
● “ John Q. Doe”
● “9999 Main Street”
● “(201) 555-1212”
Una declaración puede asignar un literal a una referencia de string:
string​ color = “blue”;
inicializa la variable color de tipo string para que refiera al objeto string literal “blue”.

String Verbatim:​ en cadenas de texto con múltiples separadores ‘\’, tales como las direcciones de
archivos, se puede emplear una secuencia de escape que interprete todos los caracteres de un
string como literales “@”, para evitar el excesivo uso de estos. esto permite generar un string
verbatim, en donde ciertos caracteres no sean considerados secuencias de escape. Esta
aproximación tiene la ventaja adicional de permitir a los literales de string ocupar múltiples líneas
preservando todas las líneas nuevas, espacios y tabs.
Ejemplo:

● Sin Verbatim:
string​ file =​ “C:\\MyFolder\\MySubFolder\\MyFile.txt”​;

● Con Verbatim:
string​ file = ​@“C:\MyFolder\MySubFolder\MyFile.txt”​;

Clase String.
Clase ​sealed ​que representa texto como una secuencia de unidades de código UTF-16.
Un string es una colección secuencial de caracteres que son empleados para representar
texto. ​Un ​objeto String​ es una​ colección secuencial de objetos System.Char que representa
un string​; ​un objeto System.Char corresponde a una unidad de código UTF-16​. El valor de
dicho objeto string es el contenido de la colección secuencial de objetos System.Char y su valor
es inmutable.

Instanciación.
1. Por asignación de un literal a una variable de tipo ​string​.
2. Empleando constructores de la clase.

Constructor Descripción

String(Char*) Inicializa la nueva instancia de la clase


String al valor indicado por un puntero
especificado de un arreglo de caracteres
Unicode.

String(Char*, Int32, Int32) Inicializa la nueva instancia de la clase


String al valor indicado por puntero
especificado de un arreglo de caracteres
Unicode, empezando desde la posición
especificada del arreglo hasta la longitud
especificada.

String(Char*, Int32) Inicializa la nueva instancia de la clase


String al valor indicado por el carácter
Unicode especificado repetido el número
de veces especificado.

String(Char[]) Inicializa la nueva instancia de la clase


String al valor indicado por un arreglo de
caracteres Unicode.
String(Char[], Int32, Int32) Inicializa la nueva instancia de la clase
String al valor indicado por un arreglo de
caracteres Unicode, comenzando por la
posición especificada dentro del arreglo
hasta la longitud especificada.

String(SByte*) Inicializa la nueva instancia de la clase


String al valor indicado por un puntero a un
arreglo de enteros de 8 bits con signo

String(SByte*, Int32, Int32) Inicializa la nueva instancia de la clase


String al valor indicado por un puntero a un
arreglo de enteros de 8 bits con signo
especificando una posición inicial dentro
del arreglo y una longitud.

String(SByte*, Int32, Int32, Encoding) Inicializa la nueva instancia de la clase


String al valor indicado por un puntero a un
arreglo de enteros de 8 bits con signo
especificando una posición inicial dentro
del arreglo, una longitud y un objeto de tipo
Encoding.

3. Empleando concatenación de strings mediante el operador ‘+’ para generar un nuevo string
que contenga dichas instancias o literales de strings.
4. Llamando a un método de conversión o formateo que transforme un valor u objeto a su
representación en string.

Propiedades.

Propiedad Descripción

Chars Obtiene el objeto Char situado en la posición


específica en el objeto String actual

Length Obtiene el número de caracteres del objeto


String actual.

Métodos.

Tipo Método Descripción

Comparación Compare Compara dos objetos string y


devuelve un entero que indica
su posición relativa en el
criterio de ordenamiento (10
sobrecargas)
CompareOrdinal Compara las dos objetos
string (o subcadenas de ellos)
especificados mediante la
evaluación de los valores
numéricos de los objetos Char
correspondientes a cada
cadena.

CompareTo Compara la instancia actual


con un objeto de tipo Object o
String especificado y devuelve
un int que indica su posición
relativa según el criterio de
ordenamiento.

Equals Determina si la instancia es


igual la del objeto
especificado como
argumento. Determina si el
objeto tiene el mismo valor
que el objeto String pasado
como argumento del método.

EndsWith Determina si el final de la


cadena de la instancia
coincide con la cadena
especificada.

StartsWith Determina si el principio de


esta instancia de cadena
coincide con la cadena
especificada.

Ubicar subcadenas y IndexOf Devuelve el índice de base


caracteres cero de la primera aparición
del carácter unicode
especificado en la cadena o
instancia de String. Se puede
iniciar la búsqueda desde una
posición especificada como
argumento del método hasta
una longitud específica.

IndexOfAny Devuelve el índice de base


cero de la primera aparición
en la instancia de un carácter
de una matriz de caracteres
Unicode especificada. Se
puede iniciar la búsqueda
desde una posición
especificada como argumento
del método hasta una longitud
específica.

LastIndexOf Devuelve la posición de índice


de base cero de la última
aparición de un carácter
Unicode especificado en la
instancia. ​Se puede iniciar la
búsqueda desde una posición
especificada como argumento
del método hasta una longitud
específica.

LastIndexOfAny Devuelve la posición de índice


de base cero de la última
aparición en la instancia de uno
o varios caracteres
especificados de una matriz de
caracteres Unicode. ​Se puede
iniciar la búsqueda desde una
posición especificada como
argumento del método hasta
una longitud específica.

Copiar una parte o la totalidad Copy Crea una nueva instancia de


del string a otro string o String con el valor de una
arreglo de caracteres. instancia String especificada.

CopyTo Copia un número especificado


de caracteres situados en una
posición especificada de la
instancia en una posición
dada de un arreglo de
caracteres Unicode.

Modificación de strings Insert Devuelve una nueva cadena


en la que se inserta una
cadena especificada en la
posición de índice concreta de
de la instancia actual.

Replace Devuelve una nueva cadena en


la que todas las apariciones de
un carácter Unicode
especificado o substring de
esta instancia se reemplazan
por otro carácter Unicode o
substring especificado.

Remove Devuelve una nueva cadena en


la que se han eliminado todos
los caracteres de la instancia
actual, a partir de una posición
especificada y hasta la última
posición o una posición
especificada.

PadLeft Devuelve una nueva cadena


que alinea a la derecha los
caracteres de la instancia e
inserta a la izquierda un
carácter Unicode especificado
o espacios en blanco hasta
alcanzar la longitud total
especificada.

PadRight Devuelve una nueva cadena


que alinea a la izquierda los
caracteres de la cadena e
inserta un carácter Unicode
especificado o espacios en
blanco a la derecha hasta
alcanzar la longitud total
especificada.

Trim Quita todos los caracteres de


espacio en blanco o de un
conjunto de caracteres
especificados del principio y el
final del objeto ​String ​actual.

TrimEnd Quita todas las apariciones del


final de un conjunto de
caracteres especificados en
una matriz del objeto String
actual.

TrimStart Quita todas las apariciones del


principio de un conjunto de
caracteres especificados en
una matriz del objeto String
actual.

Cambio ToLower Devuelve una copia de esta


mayúsculas/minúsculas cadena convertida en
minúsculas.

ToUpper Devuelve una copia de esta


cadena convertida en
mayúsculas.

Concatenar Concat Concatena la representación


de cadena de él/los Object,
arreglo de Object, Strings,
String[] o miembros de una
colección IEnumerable <T>
especificados
Join Concatena cadenas de
caracteres usando el
separador especificado entre
todos los elementos.

Extraer substring Substring Recupera una subcadena de la


instancia. La subcadena
empieza en una posición de
caracteres especificada y
continúa hasta el final de la
cadena o hasta una posición
especificada.

Dividir en substrings Split Divide una cadena en


subcadenas basadas en los
caracteres de una matriz o
separadores. Se puede
especificar un máximo de
subcadenas a devolver.

Clase StringBuilder.
Clase ​sealed ​que representa una cadena de caracteres mutable. Se emplea cuando se desea
realizar manipulaciones extensivas o repetitivas de strings (número grande o indefinido); no puede
emplearse en casos de búsqueda ya que dicha clase carece de los métodos de búsqueda que
posee la clase String. Un objeto de esta clase mantiene un buffer para alojar expansiones del
string si hay espacio disponible (capacidad), si no lo hay, la capacidad se expande para alojar a
los caracteres adicionales (el contenido del buffer anterior se copia en el nuevo buffer).

Instanciación.

Constructor Descripción

StringBuilder() Crea un objeto StringBuilder con capacidad


predeterminada (16 caracteres)

StringBuilder(Int32) Crea un objeto StringBuilder con la capacidad


especificada.

StringBuilder(Int32, Int32) Crea un objeto Stringbuilder con la capacidad


especificada y capacidad máxima dada como
argumento.

StringBuilder(String) Crea un objeto StringBuilder conteniendo el


String especificado como argumento con
capacidad de 16 caracteres o la longitud del
String dado, cualquiera sea mayor.
StringBuilder(String, Int32) Crea un objeto StringBuilder conteniendo el
String especificado como argumento con la
capacidad especificada como argumento o la
longitud del String dado, cualquiera sea
mayor.

StringBuilder(String, Int32, Int32, Int32) Crea un objeto StringBuilder conteniendo el


String especificado como argumento desde la
posición indicada, con la capacidad
especificada o la longitud del String dado,
cualquiera sea mayor y con una capacidad
máxima específica.

Propiedades.

Propiedad Descripción

Capacity Devuelve o establece el número máximo de


caracteres que pueden ser contenidos en la
memoria alocada en la instancia actual.

Chars[Int32] Devuelve o establece el carácter en la


posición especificada en la instancia actual.

Length Devuelve o establece la longitud del objeto


StringBuilder actual.

MaxCapacity Devuelve la capacidad máxima de la instancia


(por defecto Int32.MaxValue)

Métodos.

Método Descripción

Append Agrega una representación de string de un


objeto especificado al final de la cadena
actual.

AppendFormat Agrega a la instancia un string con formato,


que contiene especificaciones de formato.
Cada especificación de formato se reemplaza
por la representación en forma de cadena de
un argumento del objeto correspondiente.

AppendLine Agrega el terminador de línea predeterminado


o una copia de un string especificado y el
terminador de línea predeterminado al final de
la instancia actual.
CopyTo Copia los caracteres de un segmento
especificado de la instancia actual al
segmento especificado de un arreglo de Char
de destino.

Finalize Permite que un objeto de tipo Object intente


liberar recursos al realizar otras operaciones
de limpieza antes de que este sea reclamado
por el GC.

Insert Inserta en la instancia actual la representación


de string de un objeto especificado en la
posición dada como argumento en el método.

Remove Elimina en la instancia actual el intervalo de


caracteres especificado.

Replace Reemplaza todas las apariciones de un


carácter o substring en la instancia por otro
caracter o substring especificado.

EnsureCapacity Asegura que la capacidad de la instancia


actual es de al menos el valor especificado.

Búsquedas en un Objeto StringBuilder.


Esta clase no contiene métodos similares a los provistos por la clase String tales como
String.Contains(), String.IndexOf() o String.StartsWith(), entre otros; que permiten buscar un
carácter o substring particular dentro del objeto. La búsqueda de un carácter o substring en un
objeto StringBuilder requiere el uso de métodos de búsqueda de la clase String o métodos de
búsqueda para expresiones regulares siguiendo las siguientes técnicas:

Técnica Pro Contra

Buscar los valores de string Útil para determinar si un No puede ser empleado
antes de agregarlos a un substring existe. cuando el índice de un
objeto StringBuilder. substring es importante.

Llamar al método ToString() y Fácil de usar si se asigna todo Engorroso llamar al método
buscar en el objeto String el texto a un objeto ToString() si deben realizarse
retornado por dicho método. StringBuilder y luego se lo modificaciones antes de que
modifica. todo el texto sea agregado al
objeto StringBuilder. Debe
recordarse trabajar desde el
final del texto de dicho objeto
si se realizan cambios.

Usar la propiedad Útil si es de interés un Engorroso si el número de


Chars[Int32] para buscar carácter individual o un caracteres a buscar es grande
secuencialmente un rango de substring pequeño. o si la búsqueda es compleja
caracteres. desde el punto de vista lógico.
Resulta en un muy pobre
rendimiento para objetos que
han aumentado ampliamente
su tamaño a través de las
repetidas llamadas a
métodos.

Convertir al objeto Útil si el número de Niega el beneficioso


StringBuilder a un objeto modificaciones es pequeño rendimiento de la clase
String y realizar las StringBuilder si el número de
modificaciones en dicho modificaciones es grande.
objeto.

Struct Char.
Representa un carácter como una unidad de código UTF-16.

Operaciones comunes.

Operación Método de System.Char

Comparar objetos Char Métodos CompareTo() o Equals()

Convertir un código de punto a un string ConvertFromUtf32()

Convertir un objeto Char o un par de objetos Para un único carácter se puede emplear
Char sustitutos en un punto de código Convert.ToInt32(Char), para un par suplente o
un caracter dentro de un string se emplea
Char.ConvertToUtf32()

Obtener la categoría Unicode de un carácter GetUnicodeCategory()

Determinar si un carácter se encuentra dentro Métodos de comprobación de caracteres (​ver


de una categoría Unicode determinada tabla de métodos)​

Convertir un objeto Char que representa un GetNumericValue()


número a un valor de tipo numérico

Convertir un carácter en un string en un objeto Parse/TryParse()


de tipo Char

Convertir un objeto Char a un objeto String ToString()

Cambiar mayúsculas/minúsculas de un objeto ToLower(), ToUpper(), ToLowerInvariant() y


Char ToUpperInvariant()
Métodos.

Tipo Método Descripción

Comprobación de caracteres IsControl Indica si el carácter Unicode


(se puede emplear con el especificado se clasifica por
evento ​KeyPress ​de controles categorías como un carácter de
en WF) control.

IsDigit Indica si el carácter Unicode


especificado se clasifica por
categorías como un dígito
decimal.

IsLetter Indica si el carácter Unicode


especificado pertenece a
alguna categoría de letras
Unicode.

IsLetterOrDigit Indica si el carácter Unicode


especificado pertenece a
alguna categoría de letras o
dígitos decimales.

IsLower Indica si el carácter Unicode


especificado se clasifica por
categorías como una letra
minúscula.

IsNumber Indica si el carácter Unicode


especificado se clasifica por
categorías como un número.

IsPunctuation Indica si el carácter Unicode


especificado se clasifica por
categorías como un signo de
puntuación.

IsSeparator Indica si el carácter Unicode


especificado se clasifica por
categorías como un carácter
separador.

IsSymbol Indica si el carácter Unicode


especificado se clasifica por
categorías como un carácter de
símbolo.

IsUpper Indica si el carácter Unicode


especificado se clasifica por
categorías como una letra
mayúscula.

IsWhiteSpace Indica si el carácter Unicode


especificado se clasifica por
categorías como un espacio en
blanco.

Conversión a carácter Parse Convierte el valor de la cadena


Unicode especificada en el carácter
Unicode equivalente.

TryParse Convierte el valor de la cadena


especificada en el carácter
Unicode equivalente. Un código
devuelto indica si la conversión
fue correcta o no.

Conversión ToLower Convierte el valor de un


mayúsculas/minúsculas carácter Unicode en un
carácter equivalente, pero en
minúsculas.

ToUpper Convierte el valor de un


carácter Unicode en un
carácter equivalente, pero en
mayúsculas.

Clase Regex.
Representa una expresión regular inmutable. Pertenece al ​namespace
System.Text.RegularExpressions​.

Las expresiones regulares son un formato especial de objetos string que se utilizan para buscar
patrones en texto. Pueden ser útiles durante la validación de información ya que permiten verificar
condiciones a cumplir, representado las mismas de forma sencilla. Las expresiones regulares
utilizan “clases de caracteres” que no son comparables a las clases ya conocidas, son sólo
secuencias de escapes que representan un conjunto de caracteres que podrían aparecer en un
string.

Bibliografía.
● https://docs.microsoft.com/en-us/dotnet/api/system.string?view=netframework-4.7.2
● https://docs.microsoft.com/en-us/dotnet/api/system.text.stringbuilder?view=netframework-4.
7.2
● https://docs.microsoft.com/en-us/dotnet/api/system.char?view=netframework-4.7.2
● https://docs.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex?view=net
framework-4.7.2
● Deitel & Deitel. “How to Program: Visual C# 2012. 5th Edition”. Chapter 16.
Unidad VI: Archivos.
Para lograr la persistencia de grandes cantidades de datos incluso luego que el programa que los
creo haya terminado se emplean Archivos. Los datos mantenidos en archivos se denominan
persistentes. Los archivos son alojados en dispositivos de almacenamiento secundario (discos
magnéticos, discos ópticos, memoria flash,etc).

Jerarquía de datos.
1. Bits (binary digit): ​elemento más pequeño de dato que puede soportar una computadora;
puede asumir dos valores: 0 ó 1. Los circuitos en las computadoras realizan varias
manipulaciones sencillas de bits tales como examinar el valor de un bit, establecer el valor
de un bit o revertir dicho valor.
2. Caracteres: ​incluyen dígitos decimales, letras y símbolos especiales. El set de caracteres
empleados para escribir programas y representar ítems de datos en una computadora en
particular se denomina set de caracteres de dicha computadora. Cada carácter del set se
encuentra representado como un patrón de 0s y 1s, para permitir a la máquina su
manipulación y procesamiento. Un byte está compuesto por 8 bits. C# emplea el set de
caracteres Unicode.
3. Campos:​ Consisten en grupos de caracteres que conllevan un significado. Ej: El nombre
de una persona, un número de teléfono o documento, etc.
4. Registros: ​Se componen de varios campos relacionados y se pueden representar como
una clase. Ej: Registro de un empleado consistente en nombre, apellido, número de
identificación, cargo, etc.
5. Archivos: ​Grupo de registros relacionados. Ej: registros de todos los empleados de una
empresa.
6. Bases de Datos: ​permiten el almacenamiento de datos relacionados. La creación y el
manejo de las mismas se realiza a través de una colección de programas denominados
Sistemas de manejo de bases de datos (DBMS)​.
Los registros pueden organizarse dentro de un archivo mediante el uso de una key (llave) elegida,
que identifica al registro de forma distintiva respecto de los demás (unívocamente). Una de las
formas de organización se denomina secuencial, en la que los registros son almacenados en
orden según su campo key. Este tipo de archivo se denomina secuencial.

Archivos y Streams (Flujos).


C# ve a cada archivo como un flujo secuencial de bytes. Cada archivo termina con un
marcador/carácter de fin de archivo​ o a un número específico de byte que es registrado en una
estructura de dato administrativa mantenida por el sistema. Cuando un archivo es abierto, un
objeto se crea y un flujo es asociado a dicho objeto. Cuando una aplicación se ejecuta, el runtime
environment crea tres objetos de tipo stream que son accesibles mediante las propiedades, en
forma respectiva:

● Console.Out:​ refiere a standard output stream object, que permite a programas mostrar
datos en pantalla. Es de tipo ​TextWriter ​(Clase). Usado en los métodos ​Write() ​y
WriteLine()​.
● Console.In:​ refiere a standard input stream object, que permite a programas ingresar
datos desde dispositivos de entrada tales como el teclado. Es de tipo ​TextReader ​(Clase).
Usado en los métodos ​Read()​ y R ​ eadLine()​.
● Console.Error: ​refiere a ​standard error stream object​, que permite a programas mostrar
mensajes de error en la pantalla.

Estos objetos emplean flujos para facilitar la comunicación entre un programa y un archivo o
dispositivo particular. Hay varias clases para el procesamiento de archivos en la librería de clases
del Framework. El espacio de nombre ​System.IO​ incluye las clases ​StreamReader​,
StreamWriter ​y ​FileStream​.

Clase File.
Provee métodos estáticos para la creación, copia, eliminación, movimiento y apertura de un solo
archivo, y auxilia en la creación de objetos de tipo FileStream. Se puede emplear esta clase para
obtener o establecer los atributos o la información relacionada con la creación, acceso y escritura
de un archivo.
Muchos de los métodos de la clase devuelven otros objetos de tipo I/O cuando se crean o abren
archivos. Por defecto, acceso completo a lectura y escritura de archivos nuevos es brindada a
todos los usuarios.

Enumeraciones.
Las enumeraciones empleadas para especificar el comportamientos de varios métodos de la clase
son:
Enumeración Descripción Campos

FileAccess Especifica el acceso a lectura Read:​ permite acceso a


y escritura de un archivo. lectura.

ReadWrite:​ permite acceso a


lectura y escritura del archivo.

Write:​ permite acceso a


escritura del archivo.

FileShare Especifica el nivel de acceso Delete:​ permite la


permitido para un archivo que subsecuente eliminación de
se encuentre en uso. un archivo.

Inheritable:​ vuelve heredable


al handler del archivo por
procesos hijos.

None:​ impide compartir el


archivo.

Read:​ permite la subsecuente


apertura del archivo para su
lectura. Pueden requerirse
permisos adicionales para
acceder a la lectura del
archivo.

ReadWrite: ​Permite la
subsecuente apertura del
archivo para lectura y
escritura. Pueden requerirse
permisos adicionales para
acceder a la lectura y
escritura de un archivo.

Write: ​permite la apertura


subsecuente del archivo para
escritura. Pueden requerirse
permisos adicionales para
acceder a la escritura de un
archivo.

FileMode Especifica si los contenidos Append:​ abre el archivo si


de un archivo existente serán este existe y busca el final del
preservados o sobreescritos y archivo, o crea un nuevo
si la petición para crear un archivo. ​Solo puede
archivo existente causará una emplearse en conjunción
excepción. con FileAccess.Write​.

Create:​ especifica que el


sistema operativo debe crear
un nuevo archivo; si este ya
existe, será sobrescrito. ​Solo
puede emplearse en
conjunción con
FileAccess.Write​.

CreateNew:​ especifica que el


sistema operativo debe crear
un nuevo archivo; si el archivo
ya existe arroja la excepción
IOException​. ​Solo puede
emplearse en conjunción
con FileAccess.Write​.

Open:​ especifica que el


sistema operativo debe abrir
un archivo existente; si este
no existe se arroja la
excepción
FileNotFoundException​.
Depende del valor
especificado en FileAccess.
OpenOrCreate: ​especifica
que el sistema operativo debe
abrir un archivo existente o
crear uno nuevo de no existir
este.

Truncate:​ especifica que el


sistema operativo debe abrir
un archivo existente; cuando
se abra debe ser truncado
para que su tamaño sea cero
bytes. ​Solo puede emplearse
en conjunción con
FileAccess​.Write. Intento de
leer de un archivo abierto con
este campo causa una
ArgumentException​.

Métodos.
Método Descripción

Copy(String, String) Copia un archivo existente a un nuevo archivo.


Copy(String, String, Boolean) La sobreescritura de un archivo con el mismo
nombre solo está permitido en la sobrecarga
con el tercer argumento de tipo bool.

Exist(String) Determina si un archivo especificado


(mediante su ruta) existe.

Delete(String) Borra un archivo especificado.

Move(String, String) Mueve un archivo especificado a una nueva


localización, proveyendo de la opción para
especificar un nuevo nombre de archivo.

ReadAllLines(String) Lee todas las líneas de un archivo.

WriteAllLines(String, String[]) Crea un nuevo archivo, escribe una colección


de string en el mismo y luego lo cierra.

GetCreationTime(String) Devuelve la fecha y hora de creación de un


archivo o directorio especificado.

GetLastAccessTime(String) Devuelve la fecha y hora en el que el archivo o


directorio especificado fue accedido por última
vez.

GetLastWriteTime(String) Devuelve la fecha y hora en la que el archivo o


directorio especificado fue escrito por ultima
vez.

Open(String, FileMode) Abre un FileStream en la ruta especificada,


Open(String, FileMode, FileAccess) con el accesoa lectura y escritura
Open(String, FileMode, FileAccess, FileShare) especificado. En la sobrecarga de tres
argumentos permite especificar el modo de
acceso. En la sobrecarga con cuatro
argumentos permite especificar la opción de
compartir.

OpenRead(String) Abre un archivo preexistente para su lectura.

OpenText(String) Abre un archivo existente con codificación


UTF-8 para lectura.

OpenWrite(String) Abre un archivo preexistente o crea uno nuevo


para escritura.

Ejemplo: Uso de método para verificar la existencia de un archivo.

using​ System;
using​ System.IO;

class​ ​Test
{
​public​ ​static​ ​void​ ​Main​()
{
​string​ path = ​@"c:\temp\MyTest.txt"​;
​if​ (!File.Exists(path))
{
​// Create a file to write to.
​using​ (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine(​"Hello"​);
sw.WriteLine(​"And"​);
sw.WriteLine(​"Welcome"​);
}
}

​// Open the file to read from.


​using​ (StreamReader sr = File.OpenText(path))
{
​string​ s;
​while​ ((s = sr.ReadLine()) != ​null​)
{
Console.WriteLine(s);
}
}
}
}
Clase Directory.
Clase ​sealed ​que expone métodos estáticos para la creación, movilización y enumeración a
través de directorios y subdirectorios. Se emplea típicamente para operaciones con directorios

Métodos.
Método Descripción

CreateDirectory(String) Crea todos los directorios y subdirectorios en


CreateDirectory(String, DirectorySecurity) la ruta especificada a menos que ya existan.
En la sobrecarga con dos argumentos permite
especificar la seguridad de Windows.

Exist(String) Determina si una ruta de acceso dada refiere a


un directorio existente en el disco.

Delete(String) Borra un directorio vacía de la ruta


Delete(String,Boolean) especificada. La sobrecarga con dos
argumentos permite borrar el directorio
especificada y cualquier subdirectorios y
archivos dentro de él de ser especificado.

Move(String,String) Mueve un archivo o directorio y sus contenidos


a una nueva localización.

Ejemplo: Obtener todos los archivos de un directorio y moverlos a otra


localización.

using​ System;
using​ System.IO;

namespace​ ​ConsoleApplication
{
​class​ ​Program
{
​static​ ​void​ ​Main​(​string​[] args)
{
​string​ sourceDirectory = ​@"C:\current"​;
​string​ archiveDirectory = ​@"C:\archive"​;

​try
{
​var​ txtFiles = Directory.EnumerateFiles(sourceDirectory,
"*.txt"​);
​ oreach​ (​string​ currentFile ​in​ txtFiles)
f
{
​string​ fileName =
currentFile.Substring(sourceDirectory.Length + 1);
Directory.Move(currentFile,
Path.Combine(archiveDirectory, fileName));
}
}
​catch​ (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}

Ejemplo: Mover un directorio y todo su contenido a otro directorio.


Nota: El directorio original deja de existir una vez que fue trasladado.

using​ System;
using​ System.IO;

namespace​ ​ConsoleApplication
{
​class​ ​Program
{
​static​ ​void​ ​Main​(​string​[] args)
{
​string​ sourceDirectory = ​@"C:\source"​;
​string​ destinationDirectory = ​@"C:\destination"​;

​try
{
Directory.Move(sourceDirectory, destinationDirectory);
}
​catch​ (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
Clase FileStream.
Provee de un flujo para un archivo, permitiendo operaciones de lectura/escritura tanto sincrónicas
como asincrónicas. Se emplea para leer desde, escribir en, abrir y cerrar archivos en un sistema
de archivos.

Constructores.
Nota: Se especifican los constructores de interés para el curso.
Constructor Descripción

FileStream(String, FileMode) Inicializa una nueva instancia de la clase con


la ruta especificada y el modo de creación.

FileStream(String, FileMode, FileAccess) Inicializa una nueva instancia de la clase con


la ruta especificada, el modo de creación y los
permisos de lectura/escritura.

FileStream(String, FileMode, FileAccess, Inicializa una nueva instancia de la clase con


FileShare) la ruta especificada, el modo de creación, los
permisos de lectura escritura y los permisos
para compartir.

Propiedades.
Nota: se describen algunas propiedades seleccionadas.
Propiedad Descripción

CanRead Obtiene el valor que indica si el flujo actual soporta lectura.

CanSeek Obtiene el valor que determina si el flujo actual soporta búsqueda.

CanTimeout Obtiene un valor que determina si el flujo corriente soporta el agotamiento


del tiempo de espera.

CanWrite Obtiene un valor que indica si el flujo actual admite escritura.

Handle Obtiene el identificador (handle) de archivo del sistema operativo


correspondiente al archivo que el objeto FileStream encapsula.

Length Devuelve la longitud en bytes del flujo.

Name Obtiene la ruta de acceso absoluta del archivo abierto en FileStream.

Position Obtiene o establece la posición actual del flujo.


Ejemplo: uso de constructores.
En los siguientes ejemplos se emplean dos constructores distintos para crear un archivo, escribir
datos byte a byte y luego verificar que los datos se incorporaron correctamente.

using​ System;
using​ System.IO;

class​ ​FStream
{
​static​ ​void​ ​Main​()
{
​const​ ​string​ fileName = ​"Test#@@#.dat"​;

​// Create random data to write to the file.


​byte​[] dataArray = ​new​ ​byte​[100000];
​new​ Random().NextBytes(dataArray);

​using​(FileStream
fileStream = ​new​ FileStream(fileName, FileMode.Create))
{
​// Write the data to the file, byte by byte.
​for​(​int​ i = 0; i < dataArray.Length; i++)
{
fileStream.WriteByte(dataArray[i]);
}

​// Set the stream position to the beginning of the file.


fileStream.Seek(0, SeekOrigin.Begin);

​// Read and verify the data.


​for​(​int​ i = 0; i < fileStream.Length; i++)
{
​if​(dataArray[i] != fileStream.ReadByte())
{
Console.WriteLine(​"Error writing data."​);
​return​;
}
}
Console.WriteLine(​"The data was written to {0} "​ +
​"and verified."​, fileStream.Name);
}
}
}

--------------------------------------------------------------------------

using​ System;
using​ System.IO;

class​ ​FStream
{
​ tatic​ ​void​ ​Main​()
s
{
​const​ ​string​ fileName = ​"Test#@@#.dat"​;

​// Create random data to write to the file.


​byte​[] dataArray = ​new​ ​byte​[100000];
​new​ Random().NextBytes(dataArray);

​using​(FileStream
fileStream = ​new​ FileStream(fileName, FileMode.Create))
{
​// Write the data to the file, byte by byte.
​for​(​int​ i = 0; i < dataArray.Length; i++)
{
fileStream.WriteByte(dataArray[i]);
}

​// Set the stream position to the beginning of the file.


fileStream.Seek(0, SeekOrigin.Begin);

​// Read and verify the data.


​for​(​int​ i = 0; i < fileStream.Length; i++)
{
​if​(dataArray[i] != fileStream.ReadByte())
{
Console.WriteLine(​"Error writing data."​);
​return​;
}
}
Console.WriteLine(​"The data was written to {0} "​ +
​"and verified."​, fileStream.Name);
}
}
}

Clase StreamReader.
Implementa un TextReader que lee caracteres de un flujo de bytes en una codificación particular.
Se emplea para leer información de un archivo de texto estándar. Por defecto, lee codificación
UTF-8 a menos que se especifique de otra forma mediante la propiedad CurrentEncoding.

Constructores.
Nota: se especifican algunos constructores seleccionados.

Constructor Descripción

StreamReader(Stream) Inicializa una nueva instancia de la clase para el flujo


especificado.
StreamReader(Stream, Boolean) Inicializa una nueva instancia de la clase para el flujo
especificado, con la opcion de deteccion de marca de
orden de byte especificada.

StreamReader(Stream, Encoding) Inicializa una nueva instancia de la clase para el flujo


especificado, con la codificación de caracteres elegido.

StreamReader(String) Inicializa una nueva instancia de la clase para el nombre


del archivo especificado.

StreamReader(String, Boolean) Inicializa una nueva instancia de la clase para el nombre


del archivo especificado, con la opcion de deteccion de
marca de orden de byte especificada.

StreamReader(String, Encoding) Inicializa una nueva instancia de la clase para el nombre


del archivo especificado, con la codificación de caracteres
elegido.

Métodos.
Métodos Descripción

Close Cierra el objeto StreamReader y el flujo


subyacente, liberando cualquier recurso del
sistema asociado a la lectura.

Peek Devuelve el siguiente carácter disponible pero


no lo consume.

Read Lee el siguiente carácter del flujo de entrada y


avanza en su posición un carácter..

ReadLine Lee una línea de caracteres de la corriente de


flujo y devuelve los datos como un string.

ReadToEnd Lee todos los caracteres desde la posición


actual hasta el final del flujo.

Ejemplo: uso de StreamReader para lectura de un archivo.

using​ System;
using​ System.IO;

class​ ​Test
{
​public​ ​static​ ​void​ ​Main​()
{
​ ry
t
{
​// Create an instance of StreamReader to read from a file.
​// The using statement also closes the StreamReader.
​using​ (StreamReader sr = ​new​ StreamReader(​"TestFile.txt"​))
{
​string​ line;
​// Read and display lines from the file until the end of
​// the file is reached.
​while​ ((line = sr.ReadLine()) != ​null​)
{
Console.WriteLine(line);
}
}
}
​catch​ (Exception e)
{
​// Let the user know what went wrong.
Console.WriteLine(​"The file could not be read:"​);
Console.WriteLine(e.Message);
}
}
}

Clase StreamWriter.
Implementa un TextWriter para escribir caracteres en un flujo en una codificación particular. por
defecto, la clase emplea la codificación UTF-8 a menos que se especifique de otra forma.

Constructores.
Nota: se especifican algunos constructores seleccionados.

Constructor Descripción

StreamWriter(Stream) Inicializa una nueva instancia de la clase para el flujo


especificado empleando la codificación UTF-8 y el
tamaño de buffer por defecto.

StreamWriter(Stream, Encoding) Inicializa una nueva instancia de la clase para el flujo


especificado empleando la codificación especificada
y el tamaño de buffer por defecto.

StreamWriter(String) Inicializa una nueva instancia de la clase para el


archivo especificado empleando la codificación y el
tamaño de buffer por defecto.

StreamWriter(String, Boolean) Inicializa una nueva instancia de la clase para el


archivo especificado empleando la codificación y el
tamaño de buffer por defecto. Si el archivo existe,
puede ser sobreescrito o la información puede ser
adicionada. Si el archivo no existe, el constructor
crea uno nuevo.

StreamWriter(String, Boolean, Encoding) Inicializa una nueva instancia de la clase para la ruta
de archivo especificada empleando la codificación
especificada y el tamaño de buffer por defecto. Si el
archivo existe, puede ser sobreescrito o la
información puede ser adicionada. Si el archivo no
existe, el constructor crea uno nuevo.

Métodos.
Método Descripción

Close Cierra el objeto StreamWriter actual y el flujo


subyacente.

Dispose Libera todos los recursos empleados por el


objeto TextWriter (heredado de TextWriter)

Flush Limpia todos los buffers para el Writer actual y


produce la escritura de cualquier dato alojado
en el buffer en el dispositivo subyacente.

Write Escribe la representación en string del


argumento (Char, Char[],String, Object, UInt,
Int, Double, Single, Decimal)

WriteLine Escribe un terminador de línea al texto string o


flujo.

Ejemplo: uso de StreamWriter para escritura en archivo.


Se busca generar un archivo que liste todos los directorios que se encuentran en el disco C.

using​ System;
using​ System.Collections.Generic;
using​ System.Linq;
using​ System.Text;
using​ System.IO;

namespace​ ​StreamReadWrite
{
​class​ ​Program
{
​static​ ​void​ ​Main​(​string​[] args)
{
​// Get the directories currently on the C drive.
DirectoryInfo[] cDirs = ​new
DirectoryInfo(​@"c:\"​).GetDirectories();

​// Write each directory name to a file.


​using​ (StreamWriter sw = ​new​ StreamWriter(​"CDriveDirs.txt"​))
{
​foreach​ (DirectoryInfo dir ​in​ cDirs)
{
sw.WriteLine(dir.Name);

}
}

​// Read and show each line from the file.


​string​ line = ​""​;
​using​ (StreamReader sr = ​new​ StreamReader(​"CDriveDirs.txt"​))
{
​while​ ((line = sr.ReadLine()) != ​null​)
{
Console.WriteLine(line);
}
}
}
}
}

Ejemplo de Lectura/Escritura de Archivos.

Serialización.
Es el proceso de conversión de un objeto en un flujo de bytes para poder almacenarlo o
transmitirlo a memoria, a una base de datos o aun archivo. Su propósito principal es guardar el
estado de un objeto de modo tal de poder recrearlo cuando sea necesario. El proceso inverso se
denomina deserialización.

Proceso de Serialización.
El objeto es serializado a un flujo, el cual no solo lleva los datos, sino también la información sobre
el tipo del objeto tal como su versión, referencia cultural y sombre de ensamblado. A partir de esa
secuencia, el almacenamiento se puede realizar en una base de datos, en un archivo o en la
memoria.
Conversión de un objeto en serializable.
Para poder serializar un objeto, se debe marcar el mismo con el atributo ​[Serializable]​; una
excepción es lanzada si se intenta serializar pero el tipo no contiene el atributo ​[Serializable]​. Si
una clase serializada contiene referencias a objetos de otras clases y dichos objetos se
encuentran marcados con el atributo, los mismos serán también serializados.
Si no se desea serializar un campo particular dentro de la clase a ser serializada, se debe aplicar
el atributo ​[NonSerializable]​.

Serialización de un objeto.

Básica y binaria.
La serialización básica requiere que el objeto se encuentre marcado con el atributo ​[Serializable]​.
Es sencilla, pero no provee mucho control sobre el proceso.
La serialización binaria emplea codificación binaria para producir una serialización compacta para
usos tales como almacenamiento o flujos de redes basados en sockets. Se emplea la clase
BinaryFormatter​ (​namespace System.Runtime.Serialization.Formatters.Binary​), que permite
la escritura o lectura de objetos desde un flujo. Contiene el método ​Serialize() ​que escribe la
representación de un objeto a un archivo. El método ​Deserialize() ​de la misma clase lee esta
representación de un archivo y reconstruye el objeto original. Ambos métodos lanzan una
SerializationException ​si un error ocurre durante la serialización o deserialización. Ambos
métodos requieren un objeto de tipo ​Stream (FileStream) ​como parámetro para acceder al flujo
correcto.

Métodos de la clase BinaryFormatter para serialización.

Método Descripción

Deserialize(Stream) Deserializa el flujo especificado en un gráfico


de objeto

Serialize(Stream, Object) Serializa el objeto o gráfico de objetos con el


objeto superior (raíz) especificado, en el flujo
indicado.

Personalizada.
Se puede especificar qué objetos serán serializados y como. La clase debe estar marcada con el
atributo ​[Serializable]​ e implementar la interfaz ​ISerializable​. Si se desea que la deserialización
sea personalizada se emplea un constructor personalizado.

Ejemplo: Serialización/Deserialización Básica Binaria.

using​ System;
using​ System.IO;
using​ System.Collections;
using​ System.Runtime.Serialization.Formatters.Binary;
using​ System.Runtime.Serialization;

public​ ​class​ ​App


{
[​STAThread​]
​static​ ​void​ ​Main​()
{
Serialize();
Deserialize();
}

​static​ ​void​ ​Serialize​()


{
​// Create a hashtable of values that will eventually be
serialized.
Hashtable addresses = ​new​ Hashtable();
addresses.Add(​"Jeff"​, ​"123 Main Street, Redmond, WA 98052"​);
addresses.Add(​"Fred"​, ​"987 Pine Road, Phila., PA 19116"​);
addresses.Add(​"Mary"​, ​"PO Box 112233, Palo Alto, CA 94301"​);

​// To serialize the hashtable and its key/value pairs,


​// you must first open a stream for writing.
​// In this case, use a file stream.
FileStream fs = ​new​ FileStream(​"DataFile.dat"​, FileMode.Create);

​// Construct a BinaryFormatter and use it to serialize the data to


the stream.
BinaryFormatter formatter = ​new​ BinaryFormatter();
​try
{
formatter.Serialize(fs, addresses);
}
​catch​ (SerializationException e)
{
Console.WriteLine(​"Failed to serialize. Reason: "​ +
e.Message);
​throw​;
}
​finally
{
fs.Close();
}
}

​static​ ​void​ ​Deserialize​()


{
​// Declare the hashtable reference.
Hashtable addresses = ​null​;

​// Open the file containing the data that you want to deserialize.
FileStream fs = ​new​ FileStream(​"DataFile.dat"​, FileMode.Open);
​try
{
BinaryFormatter formatter = ​new​ BinaryFormatter();

​// Deserialize the hashtable from the file and


​// assign the reference to the local variable.
addresses = (Hashtable) formatter.Deserialize(fs);
}
​catch​ (SerializationException e)
{
Console.WriteLine(​"Failed to deserialize. Reason: "​ +
e.Message);
​throw​;
}
​finally
{
fs.Close();
}

​// To prove that the table deserialized correctly,


​// display the key/value pairs.
​foreach​ (DictionaryEntry de ​in​ addresses)
{
Console.WriteLine(​"{0} lives at {1}."​, de.Key, de.Value);
}
}
}
Ventanas modales: OpenFileDialog y SaveFileDialog.

Clases OpenFileDialog y SaveFileDialog.


OpenFileDialog​ es una clase ​sealed ​que muestra un cuadro de diálogo estándar que permite al
usuario abrir un archivo.
SaveFileDialog ​es una clase ​sealed ​que permite al usuario seleccionar una ubicación para
guardar un archivo.

Propiedades Comunes.

Propiedad Descripción

CheckFileExists Obtiene o establece un valor que indica si el


cuadro de diálogo muestra una advertencia
cuando usuario especifica un nombre de
archivo que no existe (Heredado de
FileDialog​).

CheckPathExists Obtiene o establece un valor que indica si el


cuadro de diálogo muestra una advertencia
cuando usuario especifica una ruta de acceso
que no existe (Heredado de ​FileDialog​).

DefaultExt Obtiene o establece la extensión de nombre


del archivo predeterminada (Heredado de
FileDialog​)

FileName Obtiene o establece una cadena que contiene


el nombre del archivo seleccionado en el
cuadro de diálogo del archivo (Heredado de
FileDialog​)

Filter Obtiene o establece la cadena actual de filtro


de nombres de archivo, que determina las
opciones que aparecen en los cuadros
“Guardar como archivo de tipo” o “Archivos de
tipo” del cuadro de diálogo (heredado de
FileDialog​).

FilterIndex Obtiene o establece el índice de filtro actual


seleccionado en el cuadro de diálogo
(heredado de ​FileDialog​).

InitialDirectory Obtiene o establece el directorio inicial


mostrado en el cuadro de diálogo (heredado
de ​FileDialog​).
Title Obtiene o establece el título del cuadro de
diálogo.

Métodos Comunes.

Método Descripción

Dispose() Libera todos los recursos que usa Component.

OpenFile() Abre el archivo seleccionado por el usuario


con permiso de solo lectura para
OpenFileDialog ​o de lectura/escritura para
SaveFileDialog​. En la clase ​OpenFileDialog
la propiedad FileName especifica el archivo.

ShowDialog() Ejecuta el cuadro de diálogo común con un


propietario determinado (heredado de
CommonDialog​).

Ejemplo: uso de OpenFileDialog.


Se crea un ​OpenFileDialog​, se establecen varias propiedades para definir el comportamiento
del filtro y el cuadro de diálogo de la extensión de archivo. Se muestra el cuadro de diálogo
mediante el método ShowDialog(). El ejemplo requiere un formulario con un botón y la referencia
al espacio de nombre System.IO.

var​ fileContent = ​string​.Empty;


​var​ filePath = ​string​.Empty;

​using​ (OpenFileDialog openFileDialog = ​new​ OpenFileDialog())


{
openFileDialog.InitialDirectory = ​"c:\\"​;
openFileDialog.Filter = ​"txt files (*.txt)|*.txt|All files
(*.*)|*.*"​;
openFileDialog.FilterIndex = 2;
openFileDialog.RestoreDirectory = ​true​;

​if​ (openFileDialog.ShowDialog() == DialogResult.OK)


{
​//Get the path of specified file
filePath = openFileDialog.FileName;

​//Read the contents of the file into a stream


​var​ fileStream = openFileDialog.OpenFile();

​using​ (StreamReader reader = ​new​ StreamReader(fileStream))


{
fileContent = reader.ReadToEnd();
}
}
}

MessageBox.Show(fileContent, ​"File Content at path: "​ + filePath,


MessageBoxButtons.OK);

Ejemplo: uso de SaveFileDialog


Se crea un ​SaveFileDialog​, se establecen los miembros, se llama al cuadro de diálogo usando el
método ShowDialog() y se guarda el archivo actual. El ejemplo requiere una form con un botón.

private​ ​void​ ​button1_Click​(​object​ sender, System.EventArgs e)


{
Stream myStream ;
SaveFileDialog saveFileDialog1 = ​new​ SaveFileDialog();

saveFileDialog1.Filter = ​"txt files (*.txt)|*.txt|All files


(*.*)|*.*"​ ;
saveFileDialog1.FilterIndex = 2 ;
saveFileDialog1.RestoreDirectory = ​true​ ;

​if​(saveFileDialog1.ShowDialog() == DialogResult.OK)
{
​if​((myStream = saveFileDialog1.OpenFile()) != ​null​)
{
​// Code to write the stream goes here.
myStream.Close();
}
}
}

Bibliografía.
● https://docs.microsoft.com/en-us/dotnet/api/system.io.file?view=netframework-4.7.2
● https://docs.microsoft.com/en-us/dotnet/api/system.io.directory?view=netframework-4.7.2
● https://docs.microsoft.com/en-us/dotnet/api/system.io.filestream?view=netframework-4.7.2
● https://docs.microsoft.com/en-us/dotnet/api/system.io.streamreader?view=netframework-4.
7.2
● https://docs.microsoft.com/en-us/dotnet/api/system.io.streamwriter?view=netframework-4.7.
2
● https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/serialization/
● https://docs.microsoft.com/es-mx/dotnet/api/system.runtime.serialization.formatters.binary.b
inaryformatter?view=netframework-4.7.2
● https://docs.microsoft.com/en-us/dotnet/api/system.nonserializedattribute?view=netframew
ork-4.7.2
● https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.openfiledialog?view=net
framework-4.7.2
● https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.savefiledialog?view=netf
ramework-4.7.2
● Deitel & Deitel. “How to Program: Visual C# 2012. 5th Edition”. Chapter 17.

Unidad VII: Estructuras de Datos.


Las estructuras de datos tratadas almacenan referencias a ​Object​, se pueden almacenar valores
simples y de referencia en estas, siendo los valores simples tratados como objetos.

Valores Struct Simples o Primitivos.


Cada tipo simple o primitivo tiene su ​Struct ​correspondiente en el espacio de nombres ​System
que define su tipo. Estos ​Structs ​son llamados ​Boolean, Byte, SByte, Char, Decimal, Double,
Single, Int16, UInt16, Int32, UInt32, Int64, UInt64​. Los tipos declarados con la palabra reservada
struct ​son ​tipos de valores​ (​value types​). Los tipos primitivos son alias de sus ​structs
correspondientes, por lo que variables de este tipo pueden declararse usando la palabra
reservada para el tipo primitivo o el nombre del ​struct​. Los métodos relacionados a estos tipos se
encuentran en el ​struct​.

Conversión Boxing/Unboxing.
Los tipos primitivos heredan de la clase ​ValueType ​en el espacio de nombre ​System​. Dicha
clase, a su vez, hereda de la clase ​Object ​y hace que cualquier tipo primitivo puede ser asignado
a una variable ​Object​; esto se denomina ​Conversión Boxing​ y permite que los tipos primitivos
puedan ser implementados como objetos. Esta conversión puede realizarse de forma explícita o
implícita.
Ejemplo:
int​ i = 5; ​// create an int value
object​ object1 = ( object ) i; ​// explicitly box the int value
object​ object2 = i; ​// implicitly box the int value

Una ​Conversión Unboxing​ puede ser usado para convertir explícitamente a una referencia object
en un valor de tipo primitivo.
Ejemplo:
int​ int1 = ( ​int ​) object1;​ // explicitly unbox the int value
Si se intenta realizar unboxing de forma explícita a una referencia de objeto que no refiere al valor
tipo primitivo correcto causa una ​InvalidCastException​.

Clases Autorreferenciales.
Contienen un miembro que referencia a un objeto del mismo tipo que la clase.​ Los objetos
autorreferenciales pueden unirse entre sí para formar estructuras de datos tales como listas,
colas, pilas y árboles, en donde un nodo apunta a uno o más nodos (link) en la estructura. Un link
null ​normalmente indica el final de la estructura de datos. La creación y el mantenimiento de
estructuras de datos dinámicas requiere alocación de memoria dinámica.
Ejemplo:
Se genera una clase base para formar una estructura de datos de tipo lista ligada (LinkedList). La
clase ​Node ​contiene una propiedad de tipo ​Node ​llamada ​Next ​que referencia al siguiente nodo
en la estructura de datos.

//Self-referential Node class declaration.


Class​ ​Node
{
public int​ Data {get; set;} ​//store integrer data
public​ ​Node​ Next {get; set;} ​//store reference to next Node

public​ ​Node ​(​int​ dataValue)


{
Data = dataValue;
} ​// end constructor
} // end class Node

LinkedList.
Una ​LinkedList ​(lista enlazada) es una ​colección lineal​ (secuencia) de objetos de una clase
autorreferencial, llamados ​nodos​, conectados por links de referencia. Un programa accede a la
LinkedList vía una referencia al primer nodo de la lista. Cada nodo subsecuente es accedido a
través de un miembro link de referencia alojado en el nodo previo.Por convención, el link de
referencia del último nodo de una lista es ​null ​para marcar el final de la estructura. Los datos son
almacenados en una lista enlazada de forma dinámica por lo que cada nodo se crea cuando es
necesario. Un nodo puede contener datos de cualquier tipo, incluyendo referencias a objetos de
otras clases.
Las listas enlazadas son apropiadas cuando el número de datos a ser representados en la
estructura de datos no es predecible​. Las listas enlazadas solo se llenan cuando el sistema no
tiene suficiente memoria como para satisfacer las peticiones de alocación dinámica de la misma.
La lista puede mantenerse ordenada insertando los nodos en el punto apropiado de la colección
sin necesidad de mover elementos preexistentes.
Normalmente, los nodos no se guardan de forma contigua en memoria, sino que son lógicamente
continuos.
Implementación.

Clase ListNode
Contiene dos propiedades: ​Data​, la cual puede referir a cualquier objeto, y ​Next ​que aloja una
referencia al siguiente objeto de tipo ​ListNode ​en la lista. Los constructores de esta clase
permiten inicializar el ​ListNode ​que será colocado al final de la lista o antes, respectivamente.

using ​System;

namespace LinkedListLibrary
{
// class to represent one node in a list
class ​ListNode
{
// automatic read-only property Data
public object ​Data {​get​; ​private set​;}

// automatic property Next


public​ ​ListNode ​Next {​get​; ​set​;}

// constructor to create ListNode that refers to dataValue


// and is last node in list
public ​ListNode( ​object ​dataValue )
: ​this​( dataValue, ​null ​)
{
}​ // end default constructor

// constructor to create ListNode that refers to


dataValue
// and refers to next ListNode in List
public ​ListNode( ​object ​dataValue, ​ListNode ​nextNode )
{
Data = dataValue;
Next = nextNode;
} ​// end constructor
}​ // end class ListNode
}
Clase List.
Contiene las variables de instancia privadas ​fistNode ​(primero en la lista) y ​lastNode ​(ultimo en la
lista). Los constructores inicializan las dos referencias a ​null ​y permite especificar el nombre de la
lista para mostrarlo. Los métodos ​InsertAtFront​, ​InsertAtBack​, ​RemoveAtFront​,
RemoveAtBack ​permite agregar o quitar nodos de la estructura. El método ​IsEmpty​ es un
método predicado​ que determina si la lista está vacía (el primer nodo de la lista es ​null​); este
sirve para testear una condición y no modifica el objeto al cual son llamados.

using ​System;

namespace ​LinkedListLibrary
{

// class List declaration


public class ​List
{

​ istNode ​firstNode;
private L
private L​ istNode ​lastNode;
private string​ name;​ // string like “list” to display

// construct empty List with specified name


public ​List​( ​string ​listName )
{
name = listName;
firstNode = lastNode = null;
} ​// end constructor

// construct empty List with "list" as its name


public ​List()
: ​this​( "list" )
{
} ​// end default constructor

// Insert object at front of List. If List is empty,


// firstNode and lastNode will refer to same object.
// Otherwise, firstNode refers to new node.

public void​ InsertAtFront( ​object ​insertItem )


{
if ​( IsEmpty() )
{
firstNode = lastNode = new ListNode(insertItem);
}
else
{
firstNode = new ListNode(insertItem, firstNode);
}
​ / end method InsertAtFront
} /

// Insert object at end of List. If List is empty,


// firstNode and lastNode will refer to same object.
// Otherwise, lastNode's Next property refers to new node.

public void​ InsertAtBack( ​object ​insertItem )


{
if ​( IsEmpty() )
{
firstNode = lastNode = new ListNode(insertItem);
}
else
{
lastNode = lastNode.Next = new ListNode(insertItem,
firstNode);
}
} ​// end method InsertAtBack

// remove first node from List


public object​ RemoveFromFront()
{
if ​( IsEmpty() )
{
throw new​ EmptyListException( name );
}
object ​removeItem = firstNode.Data; ​// retrieve data

// reset firstNode and lastNode references


if ​( firstNode == lastNode )
{
firstNode = lastNode = ​null​;
}
else
{
firstNode = firstNode.Next
}
return ​removeItem;​ // return removed data
​ / end method RemoveFromFront
} /

// remove last node from List


public object​ RemoveFromBack()
{
if​ ( IsEmpty() )
{
throw new ​EmptyListException( name );
}
object ​removeItem = firstNode.Data; ​// retrieve data

// reset firstNode and lastNode references


if ​( firstNode == lastNode )
{
firstNode = lastNode = ​null​;
}
else
{
ListNode current = firstNode;

// loop while current.Next is not lastNode


while​( current.Next != lastNode )
{
current = current.Next; ​// move to next node
}

// current is new lastNode


lastNode = current;
current.Next = ​null​;
} ​// end else
​return ​removeItem;​ // return removed data
}​ // end method RemoveFromBack

// return true if List is empty


public bool​ IsEmpty()
{
return ​firstNode == null;

}​ // end method IsEmpty

// output List contents


public void ​Display()
{
if ​( IsEmpty() )
{
Console.WriteLine​( "Empty " + name );
} ​// end if
else
{
Console.Write​( "The " + name + " is: " );
ListNode current = firstNode;

// output current node data while not at end of list


while ​( current != null )
{
​Console.Write​( current.Data + " " );
current = current.Next;
}​ // end while

Console.WriteLine​( "\n" );
} ​// end else
} ​// end method Display
​ / end class List
} /
}

Clase EmptyListException.
Define una excepción para indicar operaciones no válidas en una lista vacía.

using ​System;

namespace LinkedListLibrary
{

// class EmptyListException declaration


public class​ ​EmptyListException : Exception
{
// parameterless constructor
public​ EmptyListException()
:​ base​( "The list is empty" )
{
// empty constructor

} ​// end EmptyListException constructor

// one-parameter constructor
public​ EmptyListException( ​string ​name )
:​ base​( "The " + name + " is empty" )
{
// empty constructor
} ​// end EmptyListException constructor

// two-parameter constructor
public​ EmptyListException( ​string ​exception, ​Exception
inner )
: ​base​( exception, inner )
{
// empty constructor

}​ // end EmptyListException constructor

} ​// end class EmptyListException


​ / end namespace LinkedListLibrary
} /

Listas simple y doblemente enlazadas, lineales y circulares.


Las ​listas lineales simplemente enlazadas ​solo pueden recorrerse en una dirección; comienzan
con una referencia al primer nodo y cada nodo contiene una referencia al siguiente nodo en la
secuencia. La lista termina con un nodo cuyo miembro referencia (siguiente) es ​null​.
Una ​lista circular simplemente enlazada​ comienza con una referencia al primer nodo y cada
nodo contiene una referencia al siguiente nodo. El último nodo contiene una referencia que apunta
al primer nodo de la lista.
Una​ lista lineal doblemente enlazada ​permite su recorrido en dos direcciones. dicha lista es
normalmente implementada con dos referencia de inicio: una que refiere al primer elemento de la
lista, que permite el recorrido de inicio a fin; y otra que refiere al último, nodo para permitir un
recorrido de atrás hacia adelante. Cada nodo contiene una referencia para el nodo siguiente y una
para el anterior en la lista.
En una ​lista circular doblemente enlazada​. la referencia al siguiente elemento en el último nodo
apunta al primer nodo y la referencia al elemento previo en el primer nodo apunta al último nodo.

Stacks (Pilas).
Las pilas son estructuras lineales de tipo ​LIFO ​(​Last-Input-First-Output​). Las principales
operaciones para manipular pilas son ​push​, que permite añadir un nuevo nodo en el principio de
la pila; y ​pop ​que permite remover un nodo del principio de la pila. El espacio de nombres
System.Collections ​contiene la clase ​Stack p ​ ara implementar y manipular pilas que pueden
crecer o achicarse durante la ejecución de un programa.

Implementación.
Se puede implementar esta clase reutilizando la clase ​List ​mediante composición. Se emplea un
objeto privado de tipo ​List ​en la declaración de la clase y de esta forma se pueden esconder los
métodos de la clase ​List ​que no deban estar en la interfaz pública de la clase ​Stack​; la clase
implementa los métodos de la pila delegando el trabajo al método de la clase ​List ​apropiado.
using ​LinkedListLibrary;

namespace StackCompositionLibrary
{
// class stack encapsulates List’s capabilities
public class ​Stack
{
private​ ​List ​stack;

// construct empty stack


public ​Stack ()
{
stack = ​new​ ​List ​(“stack”);

} ​// end constructo​r

//add object to stack


public void ​Push (​object​ dataValue)
{
stack.InsertAtFront(dataValue);

} ​//end method Push

//remove object from stack


publix object​ Pop()
{
return ​stack.RemoveFromFront();
} ​//end method Pop

//determine whether stack is empty


public bool​ IsEmpty()
{
return ​stack.IsEmpty();
} ​//end method IsEmpty

// output stack contents


public void ​Display()
{
stack.Display();
} ​// end method Display

} ​// end class Stack


​ / end namespace StackCompositionLibrary
} /
Queues (Colas).
Estructura lineal de tipo ​FIFO ​(​First-Input-First-Output​) en donde los nodos son removidos solo
desde la cabeza (frente) de la cola y son insertados solo en la cola (final). Las operaciones se
inserción y remoción de nodos son ​enqueue ​y ​dequeue ​respectivamente.

Implementación.
Al igual que con Stack, se puede implementar esta clase reutilizando la clase ​List ​mediante
herencia. El método ​Enqueue ​llama a ​InsertAtBack​; el método ​Dequeue ​llama a
RemoveFromFront​.

Árboles.
Un árbol es una​ estructura de datos no lineal bidimensional​. Los nodos de un árbol contienen
dos o más links.

Árboles Binarios.
En estos, cada nodo contiene dos links (de los cuales ninguno puede ser ​null​). El ​nodo raíz​ es el
primer nodo del árbol. Cada link en la raíz refiere a un ​hijo​. El ​hijo izquierdo​ es el primer nodo en
el ​subárbol izquierdo​, y el​ hijo derecho​ es el primer nodo en el​ subárbol derecho​. Los hijos de
un nodo específico se denominan ​parientes​. Un nodo sin hijos se denomina ​nodo hoja (leaf
node)​.
Búsqueda en árboles de búsqueda binarios.
Un árbol de búsqueda binario (sin nodos duplicados) tiene la característica de que los valores en
el subárbol izquierdo son menores al valor en el subárbol del nodo padre; y los valores en
cualquier subárbol derecho son mayores que el valor en el subárbol del nodo padre. ​Los valores
de un árbol deben ser todos del mismo tipo​.
Para insertar un nuevo nodo, se compara el valor de este con el del nodo padre, si este es menos
se ubica el nuevo nodo a la izquierda del nodo padre y si es mayor se lo ubica en la rama
derecha. Si el valor de nuevo nodo es igual al del nodo padre, dicho valor se descarta. Mediante
este algoritmo de inserción se facilita la eliminación de duplicados.
​ s rápida,
La búsqueda en un árbol binario por un valor que coincida con el valor ​key e
especialmente en árboles compactos, en donde cada nivel de dicha estructura contiene el doble
de elementos que el nivel anterior.

Algoritmos de búsqueda para árboles binarios de enteros.


Se pueden recorrer de tres formas empleando recorridos recursivos:

Algoritmo de recorrido InOrder.


Muestra los nodos ​ordenados de forma ascendente​. Pasos:
1. Si el argumento es ​null​, no se procesa el árbol.
2. Recorra el subárbol izquierdo.
3. Procese el valor del nodo
4. Recorra el subárbol derecho

Nodos:​ 6 - 13 - 17 - 27 - 33 - 42 - 48.

Algoritmo de recorrido PreOrder.


Pasos:
1. Si el argumento es ​null​, no se procesa el árbol.
2. Procesar el valor del nodo
3. Recorrer el subárbol izquierdo
4. Recorrer el subárbol derecho.
Nodos: ​27 - 13 - 6 - 17 - 42 - 33 - 48.

Algoritmo de recorrido PostOrder.


El valor de cada nodo se lee luego de que se procesaron todos sus nodos hijos. Pasos:
1. Si el argumento es ​null​, no se procesa el árbol.
2. Recorrer el subárbol izquierdo.
3. Recorrer el subárbol derecho.
4. Procesar el valor del nodo.

Nodos:​ 6 - 17 - 13 - 33 - 48 - 42 - 27.

Para implementar búsquedas en árboles con valores de cualquier tipo en los nodos se puede
emplear la interfaz ​IComparable​ y su método ​CompareTo()​. De esta forma se puede definir un
criterio que permita ubicar a los nodos en función del algoritmo de inserción preestablecido.

Bibliografía.
● https://docs.microsoft.com/en-us/dotnet/standard/collections/
● Deitel & Deitel. “How to Program: Visual C# 2012. 5th Edition”. Chapter 19.

Unidad VIII: Colecciones y Genéricos.


El Framework .NET provee de varias estructuras de datos empacadas en clases para su
implementación, conocidas como ​Colecciones ​(​System.Collections​) las cuales permiten
almacenar colecciones de datos. Cada instancia de una de estas clases es una colección de
elementos.
El espacio de nombre ​System.Collections.Generic​ contiene clases genéricas, que permiten
almacenar elementos de cualquier tipo especificado por el usuario, evitando el inconveniente de
realizar posterior ​downcasting​. Son especialmente útiles a la hora de almacenar objetos de tipo
struct​, ya que evitan la necesidad de realizar conversiones de ​boxing/unboxing​.
El espacio de nombre ​System.Collections.Specialized ​contiene varias colecciones que soportan
tipos específicos tales como strings y bits. Tanto ​System.Collections​ como
System.Collections.Specialized​ almacenan y manipulan referencias a objetos de tipo ​Object​.
Las referencias a objetos obtenidas de estas colecciones requieren posterior ​downcasting ​a un
tipo apropiado para su uso en aplicaciones.

Las colecciones en estos espacios de nombre proveen componentes estandarizados y


reutilizables​.

Todas las clases ​Collection en el Framework .NET​ implementan alguna combinación de las
interfaces de colecciones. Estas interfaces declaran las operaciones que pueden realizarse de
forma genérica sobre varios tipos de colecciones. Todas estas interfaces se declaran en el
espacio de nombres ​System.Collections​ y tienen análogos genéricos en el espacio de nombre
System.Collections.Generics​; su implementación se provee dentro del framework.

Interfaz Descripción

ICollection Interfaz de la cual heredan IList y IDictionary.


Contiene una propiedad Count que determina
el tamaño de la colección y un método CopyTo
para copiar el contenido de la colección a un
arreglo tradicional.

IList Una colección ordenada que puede ser


manipulada como un arreglo. Provee de un
indexador para acceder a elementos con un
índice Int; posee además métodos para la
búsqueda y modificación de una colección
(Add, Remove, Contains, IndexOf)

IDictionary Una colección de valores indexados mediante


un objeto key (llave) arbitrario. Provee un
indexador para acceder a elementos con un
objeto indice y métodos para modificar la
coleccion (Add, Remove, etc). La propiedad
Keys contiene todos los objetos empleados
como índices y la propiedad Values contiene
todos los objetos almacenados.

IEnumerable Contiene un solo método, GetEnumerator, que


devuelve un objeto IEnumerator, dado que
todos los objetos pueden ser enumerados.
Collections extiende de IEnumerable, por lo
que todas las clases Collections implementan
esta interfaz directa o indirectamente.
Algunas Clases Collections en el Framework .NET.

Espacio de nombre Clase Interfaz Descripción

System Array IList Clase base de todos


los arreglos
convencionales.

System.Collections ArrayList IList Simula un arreglo


convencional, pero
crece o se achica en
función de la cantidad
de elementos (arreglo
dinámico)

BitArray ICollection Un arreglo de


booleanos eficiente en
cuanto a memoria.

HashTable IDictionary Una colección no


ordenada de pares
key-value que pueden
ser accedidos
mediante una key

Queue ICollection Colección de tipo


FIFO.

SortedList IDictionary Colección ordenada


por key de pares
key-value que puede
ser accedida
mediante la llave o
por índice.

Stack ICollection Colección de tipo


LIFO.

Dictionary IDictionary Colección genérica no


System.Collections.Generics ordenada de pares
key-value que pueden
ser accedidos
mediante una key
(equivalente a
HashTable).

LinkedList <T> ICollection Lista doblemente


enlazada.

List <T> IList ArrayList genérico.

Queue <T> ICollection Cola genérica.


Implementada como
un arreglo circular en
C#.

SortedDictionary <K, IDictionary Diccionario que


V> ordena los valores a
través de las keys en
un árbol binario.

SortedList <K, V> IDictionary SortedList genérica.

Stack <T> ICollection Pila genérica.


Implementada como
un arreglo en C#.

Clase Array.
La clase base abstracta Array, de la cual todos los arreglos heredan implícitamente, provee todos
los métodos para la creación, manipulación, búsqueda, y ordenamiento de arreglos. Se considera
una colección porque implementa la interfaz ​IList​. Tiene una capacidad fija (arreglo no dinámico).

Propiedades.

Propiedad Descripción

Length Obtiene el número total de elementos en todas


las dimensiones del arreglo.

Métodos.

Método Descripción

BinarySearch Busca en el arreglo ordenado un elemento


específico empleando las interfaces
IComparable (si se busca un objeto) o
IComparer (si se busca un valor).

Copy Copia todos los elementos del arreglo a otro


arreglo preexistente, comenzando desde la
posición especificada.

CopyTo Copia todos los elementos del arreglo a otro


arreglo de tamaño especificado.

Sort Ordena los elementos de un arreglo


empleando la interfaz IComparable.

Colecciones No Genéricas.
Referencian objetos de tipo ​Object y​ requieren ​downcasting ​para su posterior implementación en
aplicaciones.

Clase ArrayList.
Arreglo dinámico. ​Ver Unidad I: Repaso​.

Clase Stack.
Representa una colección no genérica de objetos de tipo LIFO. La capacidad (número de
elementos que la pila puede contener) aumenta en función de la adición de nuevos elementos.
Las pilas aceptan ​null ​como un valor válido y permiten elementos duplicados. Su versión genérica
se encuentra implementada como un arreglo.

Propiedades.

Propiedad Descripción

Count Obtiene el número total de elementos contenidos en la pila.

Métodos.

Método Descripción

Clear() Remueve todos los objetos de la pila.

Clone() Crea una copia superficial de la colección.

Contains(Object) determina si el elemento especificado se encuentra en la pila.

CopyTo(Array, Int32) Copia la pila a un arreglo unidimensional preexistente, comenzando


desde el índice especificado.

Peek() Devuelve el objeto en la parte de arriba de la pila sin removerlo.

Pop() Remueve y devuelve el objeto de la parte superior de la pila.


Push(Object) Inserta un objeto en la parte superior de la pila.

First() Método de extensión. Devuelve el primer elemento de la secuencia.

Last() Método de extensión. Devuelve el último elemento de la secuencia.

Clase Queue.
Representa una colección no genérica de objetos de tipo FIFO. La capacidad (número de
elementos que la cola puede contener) aumenta en función de la adición de nuevos elementos por
un factor de 2 y puede disminuirse llamando al método TrimToSize(). Las colas aceptan ​null ​como
un valor válido y permiten elementos duplicados. Se encuentra implementada como un arreglo
circular.

Propiedades.

Propiedad Descripción

Count Obtiene el número total de elementos contenidos en la cola.

Métodos.

Método Descripción

Clear() Remueve todos los objetos de la cola.

Clone() Crea una copia superficial de la colección.

Contains(Object) determina si el elemento especificado se encuentra en la cola.

CopyTo(Array, Int32) Copia la cola a un arreglo unidimensional preexistente, comenzando


desde el índice especificado.

Peek() Devuelve el objeto en la parte del principio de la cola sin removerlo.

Dequeue Remueve y devuelve el objeto del inicio de la cola.

Enqueue(Object) Inserta un objeto en la parte final de la cola.

First() Método de extensión. Devuelve el primer elemento de la secuencia.

Last() Método de extensión. Devuelve el último elemento de la secuencia.

TrimToSize() Establece la capacidad a la cantidad de elementos actuales que se


encuentran en la cola.
Genéricos.
Para evitar el uso de ​downcasting ​a un tipo apropiado, realizar conversiones​ boxing/unboxing​ y
detectar inconsistencias entre los tipos en tiempo de compilación (seguridad de tipo en tiempo de
compilación) se emplean genéricos. Esto proveen de medios para crear modelos generales,
maximizar la reutilización de código y el rendimiento :
● Métodos genéricos:​ permiten especificar, con una única declaración de método, un
conjunto de métodos relacionados.
● Clases genéricas:​ permiten especificar, con una sola declaración de clase, un grupo de
clases relacionadas.
● Interfaces genéricas: ​permiten especificar, con una sola declaración de interfaz, un
conjunto de interfaces relacionadas.
El operador​ <T> ​indica un tipo genérico. Se debe especificar un tipo al momento de la
implementación de un genérico.

Métodos Genéricos.
Las declaraciones de todos los métodos genéricos tienen una lista de parámetros de tipo
(​type-parameter list​) delimitada por ​<>​, que sigue al nombre del método. Cada lista de
parámetros de tipo contiene uno o mas parámetros de tipo, separado por comas (ej: ​<K,V>​). Un
parámetro de tipo es un identificador que se usa en lugar del nombre de un tipo en particular.
Estos pueden ser empleados para declarar el tipo de retorno, los tipos de los parámetros y los
tipos de las variables locales en la declaración de un método genérico; el tipo de parámetro actúa
como referente para el tipo del argumento que representa el tipo de dato que será pasado al
método genérico.
Implementación.

Un método genérico puede sobrecargarse, pero cada uno de los métodos sobrecargados debe
tener una firma única Un método genérico puede ser sobrecargado por métodos no genéricos con
el mismo nombre.
Clases Genéricas.
Una clase genérica provee los medios para describir una clase independientemente del tipo de
parámetro. La declaración de una clase genérica es similar a la no genérica, excepto que el
nombre de la clase se encuentra seguido de una lista de parámetros de tipo (ej: ​<T>​) y,
opcionalmente, una o mas limitaciones al tipo de parámetro.

Implementación.
Colecciones Genéricas.

Clase LinkedList <T>.


Representa una lista doblemente enlazada genérica. Cada nodo posee la propiedad ​Value​, cuyo
tipo coincide con el parámetro de tipo ​<T>​ de la LinkedList y contiene los datos almacenado; y las
propiedades de solo lectura ​Previous ​y ​Next​, que contienen las referencias al nodo anterior (null
si es el primero) y al siguiente (null si es el último), respectivamente.

Propiedades.

Propiedad Descripción

Count Obtiene el número de nodos contenidos en la


lista doblemente enlazada.

First Obtiene el primer nodo de la lista. ​Solo lectura​.

Last Obtiene el último nodo de la lista. ​Solo lectura​.

Métodos.

Método Descripción
AddAfter Agrega un nodo después de un nodo existente
especificado.

AddBefore Agrega un nodo antes de un nodo existente


especificado.

AddFirst Agrega un nodo conteniendo el valor


especificado al principio de la lista.

AddLast Agrega un nodo conteniendo el valor


especificado al final de la lista

Clear Remueve todos los nodos de la lista

Remove Remueve la primer ocurrencia del valor


especificado de la lista.

RemoveFirst Remueve el nodo al inicio de la lista.

RemoveLast Remueve el nodo al final de la lista.

Clase List<T>.
Representa una lista de objetos que puede ser accedida por índice. Provee métodos de
búsqueda, ordenamiento y manipulación de listas.

Propiedades.

Propiedad Descripción

Capacity Obtiene y establece el número de elementos


totales que la estructura de datos interna
puede contener sin redimensionarse.

Count Propiedad de solo lectura que obtiene el


número de elementos alojados en la lista (int)

Métodos.

Método Descripción

Add() Agrega un objeto al final de la lista.

AddRange(IEnumerable<T>) Agrega los elementos especificados en la


colección al final de la lista.

Clear() Remueve todos los elementos de la lista


Contains(T) Devuelve true si el objeto especificado como
argumento se encuentra en la lista, en otro
caso devuelve false.

IndexOf(T) Devuelve el índice de la primera ocurrencia del


elemento especificado como argumento en la
lista.

Insert(Int32, T) Inserta un objeto en el índice especificado


como argumento.

Remove(T) Elimina la primera ocurrencia del objeto,


especificado como argumento de la lista.

RemoveAt(Int32) Remueve de la lista el objeto que se encuentre


en el índice especificado como argumento.

RemoveRange(Int32, Int32) Elimina un número especificado de elementos


comenzando desde el índice explicitado como
argumento del método hasta el índice
indicado.

Sort() Ordena la lista (los elementos deben


implementar IComparable o la versión
sobrecargada de este método que recibe
IComparer debe ser implementada)

TrimExcess() Establece la capacidad de la lista al número


de elementos que esta contenga actualmente.

Find(predicate<T>) Busca el elemento que coincida con la


condición definida por el predicado
especificado (expresión lambda), y devuelve la
primer ocurrencia en la lista.

FindAll(predicate<T>) Busca todos los elementos que coincidan con


la condición definida por el predicado
especificado (expresión lambda) y devuelve
dichos elementos.

Bibliografía.
● https://docs.microsoft.com/en-us/dotnet/standard/collections/
● https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/
● https://docs.microsoft.com/en-us/dotnet/api/system.array?view=netframework-4.7.2
● https://docs.microsoft.com/en-us/dotnet/api/system.collections.stack?view=netframework-4.
7.2
● https://docs.microsoft.com/en-us/dotnet/api/system.collections.queue?view=netframework-
4.7.2
● https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.linkedlist-1?view=net
framework-4.7.2
● https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=netframe
work-4.7.2
● https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.stack-1?view=netfra
mework-4.8
● https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.queue-1?view=netfr
amework-4.8
● Deitel & Deitel. “How to Program: Visual C# 2012. 5th Edition”. Chapter 20 and 21.