Algunas excepciones comunes
ArgumentNullException ? una referencia nula es pasada como argumento
ArgumentOutOfRangeException ? nos hemos salido de rango, e.j. entero demasiado grande
DividedByZeroException
IndexOutOfRangeException ? se usa un índice inválidado del array
InvalidCastException
NullReferenceException ? se intenta invocar un método en un objeto que es null
OutOfMemoryException
Ejemplo excepciones
using System;
class Persona {
string nombre, apellido1;
int edad;
public Persona(string nombre, string apellido1, int edad) {
this.nombre = nombre;
this.apellido1 = apellido1;
this.edad = edad;
if (edad < 18) // La edad debe ser mayor que 18 sino excepción
throw new Exception("ERROR: Persona debajo edad legal");
this.edad = edad;
}
}
Ejemplo Excepciones
class Test {
public static void Main() {
try {
Persona p = new Persona("Diego, "Ipiña", 12);
} catch (Exception e) { // capturar excepción lanzada
Console.WriteLine(e.Message);
}
}
Se puede incluir un bloque finally también, para asegurarnos que recursos abiertos son cerrados:
try {
…
} catch {
…
} finally {
…
}
Enumeraciones
La palabra clave enum puede usarse para definir un conjunto ordenado de tipos integrales:
enum Modalidad {
Treboles=1, Rombos, Corazones, Picas
}
class Enums {
public static void Main() {
Modalidad m = Modalidad.Treboles;
System.Console.WriteLine(m); // Visualiza Treboles
}
}
Las enumeraciones por defecto empiezan de 0 a no ser que se sobreescriba esto como en el ejemplo
Delegates y Eventos
Un delegate es una referencia a un método, similar a un puntero a función en C++, se suelen usar para implementar manejadores de eventos y callbacks:
using System;
public delegate void Callback(string name);
public class DelgHola {
public static void Main(string[] args) {
string nombre = "Amigo";
if (args.Length > 0) nombre = args[0];
Callback cb = new Callback(diHola);
cb(nombre);
}
private static void diHola(string nombre) {
Console.WriteLine("Hola, {0}", nombre);
}
}
Delegates y Eventos
Toda aplicación gráfica usa eventos para notificar cambios (botón pulsado)
Los eventos son manejados por un manejador de eventos
Se pueden crear manejadores propios o usar los provistos por FCL como System.EventHandler
Vamos a crear un reloj usando la clase System.Timers.Timer y el delegate System.Timers.ElapsedEventHandler
El objeto Reloj creará un objeto System.Timers.Timer y registrará un manejador de evento para el evento Timer.Elapsed
ElapsedEventHandler tickHandler = new ElapsedEventHandler(Tic);
Timer.Elapsed += tickHandler;
El operador += se usa para añadir una instancia del delegate al evento, se pueden añadir varios manejadores de eventos porque ElapsedEventHandler es un delegate multicast.
Delegates y Eventos
using System.Timers;
public class Reloj {
public Reloj(int intervalo) {
this.totalTiempo = 0;
this.intervalo = intervalo;
System.Timers.Timer timer = new System.Timers.Timer();
ElapsedEventHandler tickHandler = new ElapsedEventHandler(Tic);
timer.Elapsed += tickHandler;
timer.Interval = intervalo * 1000;
timer.Enabled = true;
}
public void Tic(object source, ElapsedEventArgs e) {
this.totalTiempo += this.intervalo;
Console.WriteLine("{0}: {1} segundo tic, tiempo pasado: {2}", source, this.intervalo, this.totalTiempo);
}
private int intervalo;
private int totalTiempo;
}
Delegates y Eventos
public class MyReloj {
public static void Main() {
Reloj c1 = new Reloj(3);
Reloj c2 = new Reloj(1);
Console.WriteLine("Reloj en funcionamiento, usar Ctrl-c para acabar");
while (true) Thread.Sleep(500);
}
}
Interfaces
Los interfaces en C# permiten especificar un contrato que una clase que lo implementa ha de cumplir
Clases o estructuras en C# pueden implementar varios interfaces
Los interfaces IComparable e IEnumerable se usan frecuentemente en .NET
IComparable: interfaz a implementar para definir una comparación específica a un tipo de datos
Para poder aplicar un foreach a una colección es necesario que la colección implemente la interfaz System.Collections.IEnumerator
Ejemplo Interfaces
using System;
interface ISaludo {
void Saludar();
}
class Persona: ISaludo {
protected string nombre, apellido1;
public Persona(string nombre, string apellido) {
this.nombre = nombre;
this.apellido1 = apellido1;
}
public void Saludar() {
Console.WriteLine("Hola " + this.nombre + " " + this.apellido1);
}
public static void Main() {
Persona p = new Persona("Diego", "Ipiña");
p.Saludar();
}
}
Directivas de preprocesadores
C# define algunas directivas de procesador de C++:
#define/ #undef ? define/borra un símbolo
#if-#elif-#else-#endif ? evalua un símbolo y actúa de acuerdo a ello
#warning ? advertencia
#error ? genera un error desde una posición del código
#region/#endregion ? usado por Visual Studio.NET para marcar inicio/fin de región
Como ejemplo vamos a ilustrar como introducir código opcional para propósito de depuración, usando directivas #define e #if.
En vez de incluir #define DEBUG en el código, pasaremos en tiempo de compilación un parámetro al programa creado:
csc /define:DEBUG preproc.cs
Directivas de preprocesadores
class PreProc {
public static void Main() {
System.Console.Write("Hola, ¿cómo te llamas?");
string nombre = System.Console.ReadLine();
#if DEBUG
System.Console.WriteLine("Usuario introducido: " + nombre);
#endif
if (nombre.Equals(""))
nombre = "Amigo";
System.Console.WriteLine("Hola, " + nombre);
}
}
Atributos
C# provee un mecanismo para especificar información declarativa extra a través de varios atributos
Esta información se puede recuperar y usar en tiempo de ejecución
Algunos atributos predefinidos por .NET Framework son:
AssemblyVersion ? especifica versión de una assembly
Serializable ? indica que un tipo es serializable
WebService y WebMethod ? para servicios Web
El siguiente ejemplo muestra como podemos llevar a cabo el proceso de debugging antes ilustrado usando atributos.
El método de debug declarado y todas las llamadas al mismo, sólo serán compiladas en el programa si DEBUG es definido.
Se pueden definir atributos personalizados derivando de System.Attribute
Ejemplo: csc /define:DEBUG preproc.cs
Atributos
using System;
using System.Diagnostics;
class Go {
public static void Main() {
Console.Write("Hola, ¿cómo te llamas?");
string nombre = Console.ReadLine();
debug("usuario introducido " + nombre);
if (nombre.Equals(""))
nombre = "Amigo";
Console.WriteLine("Hola: " + nombre);
}
[Conditional("DEBUG")]
private static void debug(string msg) {
Console.WriteLine("DEBUG: " + msg);
}
}
Threading
Multithreading crea el efecto de varias tareas ejecutándose simultáneamente
El módulo System.Threading ofrece amplio suporte para ello.
Vamos a usar el delegate ThreadStart y la clase Thread para implementar el reloj antes ilustrado
using System;
using System.Threading;
public class ThreadReloj {
public static void Main() {
// crear delegate del thread
ThreadStart relojThread = new ThreadStart(empiezaReloj);
Thread t = new Thread(relojThread);
Console.WriteLine("empezando el thread …");
t.Start();
t.Join();
Console.WriteLine("thread parado");
}
Threading
private static void empiezaReloj() {
int timeElapsed = 0;
Console.WriteLine("ejecutando nuevo thread …");
for (int i=0; i<5; i++) {
Thread.Sleep(1000);
Console.WriteLine("Tic: " + (++timeElapsed));
}
}
}
Página anterior | Volver al principio del trabajo | Página siguiente |