Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Facultad de Ingeniería
Tutorial Csharp
Variables y Constantes
Una variable o una constante representan un posición de memoria ocupada por un tipo de
dato. Una varible puede ser local, el parámetro de un método, el elemento de un array, un
campo de una instancia de un objeto o un campo estático de un objeto, y su valor puede ser
modificado, en cambio, el valor de una constante siempre es el mismo.
Dado que C# es fuertemente tipificado todas las variables y constantes tienen asociado un
tipo que define los posibles valores que puede tomar.
En C# a todas las variables y constantes se les debe asignar un valor antes de poder
utilizarlas. Esta asignación de valor puede ser tanto explícita como automática a través de la
asignación del valor por defecto para un tipo. Estos son los valores por defecto para los
diferentes tipos:
Cuando intentamos utilizar una variable sin asignarle un valor se producirá un error como
sucede con el siguiente ejemplo:
// variable.cs
using System;
{
int v;
public Variable() {} // v = valor por defecto
public Variable(int a) { v = a; } // v = a
Variable v;
console.WriteLine(v); // error, v sin asignar
}
}
Espacios de nombres
En C# se podemos utilizar espacios de nombres para agrupar de forma lógica ciertas
porciones de código de forma que se les asocia un nombre para su uso. Si no utilizamos
explícitamente ningún espacio de nombres estaremos utilizando el espacio de nombres
global, como se hace en el primer ejemplo holamundo.cs. Veamos ahora como utilizar
explícitamente el espacio de nombres System en holamundo2.cs de forma que no tengamos
que escribir System. cada vez que nos queramos referir a alguna variable, clase, ... que esté
definida en su interior. Para ello deberemos emplear using.
// holamundo2.cs
// espacios.cs
// anidado.cs
using System;
namespace Exterior
{
namespace Interior
{
class Hola
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
{
public Hola() { Console.WriteLine("¡Hola!"); }
}
}
}
using Exterior.Interior;
class EspacioNombresAnidado
{
Alias
En C# se pueden crear alias de tipos y espacios de nombres, con lo que podremos referirnos
a ciertos tipos y espacios de nombres utilizando otro nombre distinto al que tienen en su
declaración.
// alias.cs
class Alias
{
public static void Main()
{
cadena c = "¡Hola, mundo!";
sys.Console.WriteLine(c); // ¡hola, mundo!
sys.Console.WriteLine(c.GetType()); // System.String
}
}
queremos que este se llame igual que una palabra reservada por el
lenguaje, pero sin que se considere parte de él. Así las variables x y @x son iguales. Las
letras mayúsculas y minúsculas crean identificadores diferentes.
Tipos predefinidos
Los tipos predefinidos en C# son alias de tipos en el espacio de nombres System. Aquí
podemos ver la lista completa de los mismos:
A todos estos tipos, salvo object y string, se les denomina tipos simples. Todos los tipos y
sus alias pueden utilizarse indistintamente. De esta forma podemos declarar un entero
utilizando tanto int como System.Int32:
int x = 123;
System.Int32 x = 123;
Console.WriteLine(x.GetType());
Tipos valor
Estos tipos son los más sencillos de comprender. Directamente contienen los datos, por
ejemplo, un tipo int contiene su valor, o un tipo bool vale true o false. Una de sus
características es que cuando se asignan el valor de una variable a otra, se crea una copia de
dicho valor.
// valor.cs
using System;
class Valor
{
static void Main()
{
int x = 3;
int y = x; // y es una copia de x
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
++x; // incrementa x a 4
Console.WriteLine("x = {0} y = {1}", x, y);
}
}
Este ejemplo crea dos variables de tipo int, x e y. Inicialmente x vale 3 e y pasa a ser una
copia de x. Al incrementar el valor de x, el valor de y no cambia puesto que ambos valores
son copias independientes en memoria.
Todos los tipos simples y sus combinaciones a través de structs pertenecen a esta categoría.
Tipos referencia
Los tipos referencia son algo más complejos. En un tipo referencia hemos de diferenciar
entre un objeto y una referencia a un objeto. Veamos con un ejemplo cada una de estas
partes:
// referencia.cs
using System;
using System.Text;
class Referencia
{
static void Main()
{
StringBuilder x = new StringBuilder("hola");
StringBuilder y = x;
x.Append(", ¿estás aprendiendo mucho?");
Console.WriteLine("x = '{0}' y = '{1}'", x, y);
}
}
En este caso StringBuilder es un tipo referencia, a diferencia de int que era un tipo valor.
Cuando se declara x en el ejemplo anterior, realmente se están haciendo dos cosas a la vez:
StringBuilder x;
x = new StringBuilder("hola");
StringBuilder y = x;
Com esta linea también se llevan a cabo dos acciones diferentes: por un lado se crea una
nueva referencia, y, a un objeto de tipo StringBuilder y por otro lado se hace que y apunte
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
Los tipos object y string, asi como cualquier clase definida por nosotros pertenece a esta
categoría de tipos.
// param.cs
using System;
Este mismo ejemplo podría haberse creado utilizando foreach, que es estructura que
permite crear un bucle sobre una colleción.
// param2.cs
using System;
Arrays
Un array es una colección de objetos que se almacenan de forma consecutiva en un bloque
de memoria. Para crear uno hemos de especificar el tipo de los elementos junto a [] y el
nombre que deseemos darle. A continuación, y de forma opcional, podemos crearlo e
inicializarlo. Veamos un ejemplo:
Esta línea declara un array de 5 elementos de tipo char y después lo inicializa con 5 valores.
Para acceder a cada uno de los elementos del array utilizaremos el operador [] y el número
de posición al que deseamos acceder, teniendo en cuenta que los elementos se empiezan a
numerar desde 0.
Una vez creado un array no puede modificar su longitud. Para conocer esta se puede utilizar
la propiedad de sólo lectura Lenght. Existe un conjunto de colecciones mucho más
complejas y versátiles dentro de System.Collection.
Arrays multidimensionales
Los arrays pueden tener más de una dimensión y entonces se clasifican en dos grupos:
rectangulares y dentados. Los arrays rectangulares tienen una estructura multidimensional
rectangular en la que cada dimensión posee siempre un mismo número de elementos. En
cambio en los arrays dentados, lo que hay es un array de arrays, con lo cual cada subarray
puede tener un tamaño diferente.
// array rectagular
int[,,] matriz1 = new int[3, 4, 5]; // cubo 3x4x5
// array dentado
int[][][] matriz2 = new int[3][][]; // cubo 3x_x_
for (int i = 0; i < 3; ++i)
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
{
matriz2[i] = new int[4][];
for (int j = 0; j < 4; ++j)
matriz2[i][j] = new int[5];
}
// acceso a un elemento
matriz1[1,1,1] = matriz2[1][1][1] = 7;
// getlenght.cs
using System;
// array dentado
int[][][] cosa = new int[3][][]; //
for (int i = 0; i < cosa.Length; ++i)
{
cosa[i] = new int[i + 1][];
for (int j = 0; j < cosa[i].Length; ++j)
cosa[i][j] = new int[i + j + 1];
}
Inicialización de arrays
Para inicializar un array hemos de añadir una lista de elementos entre llaves, {}, y separados
por comas.
Algunos partes de esta sintaxis de inicialización pueden omitirse, de forma que las
siguientes declaraciones son completamente equivalentes a las anteriores:
Paso de parámetros
Paso de parámetros por valor
Por defecto en C# los parámetros son pasados por valor, lo que implica crear una copia de
una variable para poder pasársela a un método.
// pasovalor.cs
using System;
// ref.cs
using System;
El modificador out
Siguiendo con la línea de asegurar que una variable es asignada antes de utilizarse que C#
promueve, out es un modificador que nos obliga a asignar un valor a una variable antes de
finalizar un método.
// out.cs
using System;
El modificador params
El modificador de parámetros params puede utilizarse en el último parámetro de cualquier
método para indicar que dicho método acepta cualquier número de parámetros de ese tipo
particular. De esta forma se pueden crear métodos con un número variable de parámetros.
// params.cs
using System;
Clases
En C# un programa se crea mediante la definición de nuevos tipos. De hecho, en C# todos
los tipos son clases. Cada nuevo tipo estará formado por un conjunto de datos y funciones.
Veamos un ejemplo:
// clase.cs
using System;
// declaración de la clase
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
class Persona
{
// una variable que contendrá el nombre
string nombre;
Campos
Los campos de una clase son los datos que esta contiene. En su forma más sencilla pueden
ser una simple declaración de variable como:
string nombre;
A los campos no estáticos (por defecto) se les denomina variables de instancia y los campos
estáticos variables de clase. Mediante el uso explícito de la palabra static hacemos que de
una variable pase a haber una única copia compartida por todas las instancias de una clase.
// static.cs
using System;
class Persona
{
static int contador;
int id;
public int Id
{
get { return id; }
}
El modificador readonly nos permite evitar que una variable sea modificada una vez que
sea asignada. Al igual que una constante posee un valor invariable, pero este se calcula en
tiempo de ejecución en vez de en tiempo de compilación. Las constantes tienen la ventaja
de permitir realizar un mayor número de optimizaciones sobre ellas. En cambio las
variables readonly, nos aportan un mayor grado de flexibilidad, pues pueden retrasar el
calcular su valor hasta la ejecución del programa. Esto puede aportar ventajas a la hora de
modificar su valor sin tener que recompilar el código para que el nuevo valor surta efecto,
como a la hora de corregir un valor erróneo o simplemente actualizarlo.
Propiedades
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
// propiedades.cs
using System;
class Persona
{
int nacimiento; // año de nacimiento
Indexadores
Los indexadores son una forma cómoda de acceder a una colección de objetos contenida
dentro de una clase a través del uso de la sintaxis de los arrays. Al igual que las
propiedades, permiten acceder a datos contenidos en un objeto, pero en vez de hacerlo a
través de un nombre, lo hacen a través de un índice. Su forma de utilización también es
similar.
// indexador.cs
using System;
class Nota
{
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
float[] notas;
Métodos
Un método es un función o procedimiento definida en el interior de una clase. En C# todo
el código se ejecuta como un método de alguna clase, pues todos los tipos que podemos
usar son clases, e incluso, la función Main, es en realidad un método de alguna clase.
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
Dentro de una clase podemos tener diferentes métodos aunque tengan el mismo nombre. A
esto se lo denomina sobrecarga de métodos. Podremos utilizar la sobrecarga siempre que
la firma de los métodos que intentemos sobrecargar sea diferente, es decir, sus parámetros
no tenga idénticos tipos y modificadores. Para la sobrecarga no se tiene en cuenta el tipo de
retorno ni el modificador params.
Constructores
Los constructores son un tipo especial de métodos que poseen las clases y cuya finalidad es
inicializar los campos de un objeto. Cada vez que se crea una nueva instancia de un objeto,
el sistema le asigna la cantidad de espacio que necesite en el montículo ("heap") y acto
seguido ejecuta el constructor de la clase para llevar a cabo la inicialización de todas los
campos que lo requieran. A diferencia de otros métodos el constuctor no puede tener tipo
de retorno ni tener otro nombre diferente del de la propia clase en que se define.
class Persona
{
public Persona(... lista de parámetros ...)
{
... código de inicialización ...
}
}
Los constructores pueden sobrecargarse, de forma que podemos tener varios de ellos y
hacer que antes de ejecutar el cuerpo de su método se ejecute otro utilizando this.
class Persona
{
public string nombre;
// inicializacion.cs
using System;
class Persona
{
public string nombre = "José Expósito";
Estudiemos ahora como afecta el uso de la palabra clave static a la inicialización de una
clase. Si la aplicamos al constructor, al igual que ocurria con la variables, tiene el efecto de
hacer que el código que ejecuta sea compartido por todas las instancias de una clase. Este
tipo de constructores se ejecutan antes de la creación de cualquier instancia de la clase, y
por supuesto, esto sucede una única vez. Cada clase puede poseer un único constructor de
este tipo y no puede tener parámetros. En el caso de las variables estáticas, como sucedía
con las no estáticas, estas se inicializan antes de la llamada al constructor estático. En
resumen, el orden de inicialización es:
1. variables estáticas
2. constructores estáticos
3. variables no estáticas
4. constructores no estáticos
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
Destructores
Los destructores son el equivalente de los constructores pero a la hora de deshacernos de la
instancia de un objeto. Cada vez que el recolector de basura de C# decide eliminar un
objeto de memoria, antes, ejecuta este método. A diferencia de los constructores es único
(no puede se puede sobrecargar) y no podemos decidir cuando es llamado. Su nombre ha de
estar formado por el símbolo ~ seguido del nombre de la clase.
class Persona
{
public Persona( ... parámetros ... ) { ... código del constructor ... }
~Persona() { ... código del constructor ... }
}
Clases anidadas
Una clase anidada es una clase decladara dentro del ámbito de otra. El anidamiento de
clases nos proporciona tres beneficios:
Una clase anidada puede acceder a cualquier miembro del la clase que lo contiene,
independiemtemente de los modificadores de acceso que este posea.
Una clase anidada puede ser ocultada, si interesa, mediante el uso de modificadores
de acceso.
Para acceder a una clase anidada desde fuera de la clase que la engloba habremos de
utilizar el nombre de la clase que la engloba.
// anidada.cs
using System;
class A
{
private int x = 3; // miembro privado (acceso por defecto)
class B
{
static void Main()
{
A.Anidada anidada = new A.Anidada()
anidada.Prueba();
}
}
Herencia
Una clase puede herendar de otra para extender o particularizar a la clase original. Heredar
de una clase nos permite reutilizar su funcionalidad sin tener que comenzar desde cero. Una
clase sólo puede heredar de otra, pero en cambio no hay límite a número de descendientes
que pueda tener. Todas las clases forman parte de una jerarquía única de clases cuya raiz es
la clase Object. Una jerarquía de clases bien diseñada se caracteriza por generalizar, de
forma razonable, los nombres del espacio de un problema. De esta forma, podriamos tener
una jerarquía de figuras geométricas con la siguiente estructura:
class Figura {}
class Rectangulo: Figura {}
class Cuadrado: Rectangulo {}
class Elipse: Figura {}
class Circulo: Elipse {}
Veamos como podemos utilizar la herencia para reutilizar código y datos de la clase Figura
en las clases Rectangulo y Cuadrado:
// figura.cs
using System;
public float Lado { get { return alto; } set { alto = ancho = value; }
}
}
class Prueba
{
public static void Main()
{
Figura f = new Figura(1, 2);
f.Mostrar();
Conversión de clases
Las variables de una clase pueden convertirse a otro tipo del que han heredado ("upcast") o
convertirse en un tipo que ha heredado de él ("downcast"). En caso de fallar un conversión
a un tipo derivado, se lanzará un excepción de tipo InvalidCastException.
Figura f = c; // upcast
c = (Cuadrado)f; // downcast
El operador as asiga null a una variable en caso de fallar una conversión a un tipo padre:
c = f as Cuadrado;
if (f is Cuadrado)
((Cuadrado)f).Lado = 5;
else
{
f.Alto = 5;
f.Ancho = 5;
}
Polimorfismo
El polimorfismo es la habilidad para relizar una misma operación sobre tipos diferentes
mientras estos compartan una serie de características comunes. Esto se puede conseguir
mediante la herencia o bien implementado un interfaz. Veamos un ejemplo de clase,
Polimorfismo, que utiliza el polimorfismo para realizar un operación sobre diferentes tipos:
class Polimorfismo
{
public static void Mostrar(Figura f)
{
Console.Write("usando polimorfismo para mostrar: ");
f.Mostrar();
}
Métodos virtuales
Un aspecto clave del polimorfismo es la capacidad de cada tipo para relizar una acción de
una forma particular. Las clases base pueden tener métodos virtules que permitan a las
clases derivadas proporcionar su propia implementación de un método. En la clase base
hemos de utilizar la palabra clave virtual en el método que deseemos particularizar en una
clase derivada. Después, en la clase derivada tendremos que utilizar override para indicar
que vamos a proporcionar una nueva implementación de un método. Utilizando el mismo
ejemplo anterior, ahora implementaremos los métodos que nos muestren la fórmula para
calcular el área de una Elipse y un Circulo:
todos los métodos que carezcan de ella. Veamos un ejemplo que nos
permita definir un método que devuleva el área de un figura geométrica:
// abstrac.cs
class Abstract
{
public static Main()
{
Figura[] figuras = new Figura[3];
De la misma forma podemos sellar un método virtual de forma que podemos asegurar su
comportamiento al no permitir que pueda ser sobrecargado posteriormente en una clase
derivada.
Modificadores de acceso
Para favorecer la encapsulación (esconder la implementación de un objeto que no
comtribuye a sus características esnciales) una clase o sus componentespueden controlar
quien puede acceder a ellos:
Estructuras
Una estructura es similar a una clase. Se declaran utilizando la palabra clave struct. Las
principales diferencias con una clase son:
Una clase es un tipo referencia mientras que una estructura es un tipo valor. En
consecuencia, las estructuras suelen utilizarse para declarar tipos simples en que la
semántica de tipo-valor sea deseable.
Una estructura no puede heredar de una clase ni de otra estructura. Tampoco puede
ser la base de una clase. Sin embargo, heredan de la clase object. Al igual que las
clases, las estructuras pueden implementar interfaces.
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
// struct1.cs
using System;
struct SimpleStruct
{
private int xval;
public int X
{
get { return xval; }
set { if (value < 100) xval = value; }
}
class TestClass
{
public static void Main()
{
SimpleStruct ss = new SimpleStruct();
ss.X = 5;
ss.DisplayX();
}
}
A causa de que son tipos valor, cuando son pasados a un método, se pasan por valor en
lugar de por referencia como ocurre con las clases.
// struct2.cs
using System;
class TheClass
{
public int x;
}
struct TheStruct
{
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
public int x;
}
class TestClass
{
public static void structtaker(TheStruct s)
{
s.x = 5;
}
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
struct PosicionExplicita
{
[FieldOffset(0)]
public byte b0;
[FieldOffset(1)]
public byte b1;
[FieldOffset(2)]
public byte b2;
[FieldOffset(3)]
public byte b3;
[FieldOffset(0)]
public int i0;
[FieldOffset(1)]
public int i1;
[FieldOffset(0)]
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
public long l;
}
Interfaces
Un interfaz nos permite hacer que múltiles clases compartan ciertas características no
presentes en una clase base. Un interfaz tiene cierto parecido a una clase, pero con
diferencias significaticas:
Métodos
Propiedades
Indexadores
Eventos
interface Dibujable
{
void Dibujar();
}
if (Alto > 0)
{
string s = "";
for (int x = 0; x < Ancho; ++x)
s += "[]";
Console.WriteLine(s);
if (Alto > 2)
{
for (int y = 0; y < Alto - 2; ++y)
{
s = "[]";
for (int x = 0; x < Ancho - 2; ++x)
s += " ";
if (Ancho > 1)
s += "[]";
Console.WriteLine(s);
}
}
if (Alto > 1)
{
s = "";
for (int x = 0; x < Ancho; ++x)
s += "[]";
Console.WriteLine(s);
}
}
}
}
Al igual que ocurria en la herencia, podremos extender un interfaz. Con ello lograremos
crear un nuevo interfaz que posea más características que aquel del que deriva.
interface Dibujable
{
void Dibujar();
}
Puede darse el caso en que en una misma clase o estructura se cree un conflito de nombres
al intentar heredar de una clase base y un interfaz un método o propiedad con el mismo
nombre. Para resolver este problema hemos de C# permite implementar explicitamente al
menos uno de los miembros del interfaz que generan el conflito. Veamos un ejemplo:
interface Figura
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
{
void Dibujar();
}
interface Dibujable
{
void Dibujar();
}
Para acceder ahora a cualquiera de estos métodos habremos de realizar una conversión al
tipo de interfaz adecuado de la siguiente forma:
Figura f = (Figura)r;
Dibujable d = (Dibujable)r;
r.Dibujar();
d.Dibujar();
Enumeraciones
Las enumeraciones permiten crear un grupo de constantes numericas asociadas a un
nombre. Veamos un ejemplo:
Para utilizarlas tenemos que declarar una variable del tipo de la enumeración y asignarle un
valor dentro de los que dicha enumeración posea.
Por defecto, a cada valor de la enumeración se le asigna como valor una constante entera 0,
1, 2,... Opcionalmente se puede especificar un tipo numérico alternativo y, además,
asignarle un valor de este tipo a cada uno de los componentes.
[Flags]
public enum Rumbo: byte {Norte = 1, Sur = 2, Este = 4, Oeste = 8};
El tipo System.Enum proporciona una gran cantidad de métodos estáticos muy útilies para
manejar las enumeraciones:
// enum.cs
using System;
class Prueba
{
public static void Main()
{
Type t = Enum.GetUnderlyingType(typeof(Logico));
Console.WriteLine(t); // imprime "Byte";
Sobrecarga de operadores
La sobrecarga de operadores permite a especificar la implementación de operador siempre
que uno o los dos operandos sean clases definidas por el usuario o una estructura. Los
operadores son métodos, cuya sintaxis es un tanto especial. La lista de operadores
sobrecargables es: +, -, !, ~, ++, --, /, %, &, |, ^, <<, >>, ==, !=, <, >, <=, >=. Veamos en
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
// complex.cs
using System;
Excepciones
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
// exception.cs
using System;
class Exception
{
public static void Main()
{
int v0 = 0;
int v1 = 1;
v1 = v1 / v0;
}
}
Para manejar excepciones se utilizan las palabras reservadas try,catch y finally. El bloque
try tiene dos propósitos: permitir a u n bloque catch capturar un excepción y asegurar que
se ejecutará el bloque finally. Un bloque try debe estar seguido por un o más bloques catch
y finally.
try
{
código que sospechamos que pueda lanzar una excepción
}
catch (TipoDeException1 e)
{
código para reaccionar a excepciones de tipo TipoDeException1
}
catch (TipoDeException2 e)
{
código para reaccionar a excepciones de tipo TipoDeException2
}
...
catch (TipoDeExceptionN e)
{
código para reaccionar a excepciones de tipo TipoDeExceptionN
}
finally
{
código que se ejecuta siempre después de try,
tanto si se lanza una excepción como si no
}
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
La acción por defecto cuando se lanza una excepción y esta no es adecauadamente tratada
dentro de un bloque catch es abortar el programa, que es lo que sucede en el ejemplo
exeception.cs. Veamos como podemos resolver esta situación:
// exception2.cs
using System;
class Exception
{
public static void Main()
{
int v0 = 0;
int v1 = 1;
try
{
v1 = v1 / v0;
}
catch (DivideByZeroException exception)
{
Console.WriteLine("Excepción: {0}", exception.Message);
}
finally
{
Console.WriteLine("Supongo que ya se ha resulto el problema,
¿no?");
}
}
}
Para poder atrapar una excepción dentro de un bloque catch, esta debe ser de tipo
System.Exception o derivar de este. Las excepciones de tipo System.Exception son las
más generales posibles. Normalmente intentaremos atrapar excepciones de algún tipo más
específico que nos permita saber más acerca de la excepción lanzada y así tener más
medios para resolver la situación. A la hora de crear una clase podemos preveer que tipo de
errores pueden darse y derivar tipos de excepciones de para intentar resolver dichos errores.
Nosotros podemos lanzar explícitamente una excepción mediante la palabra reservada try.
Algunas de las excepciones más comunes y por ello ya definidas son:
System.OutOfMemoryException
System.NullReferenceException
Syste.InvalidCastException
Syste.ArrayTypeMismatchException
System.IndexOutOfRangeException
System.ArithmeticException
System.DevideByZeroException
System.OverFlowException
Pontificia Universidad Católica del Ecuador
Facultad de Ingeniería
// exception3.cs
using System;
class Exception
{
public static void Main()
{
int[] array = {1, 2, 3};
try
{
for (int i = 0; i < 5; ++i)
Console.WriteLine("array[{0}] = {1}", i, array[i]);
}
catch (OutOfMemoryException e)
{
Console.WriteLine("Excepción: {0}", e.Message);
}
catch (IndexOutOfRangeException e)
{
Console.WriteLine("Excepción: {0}", e.Message);
}
catch
{
Console.WriteLine("Excepción general");
}
finally
{
Console.WriteLine("Supongo que ya se ha resulto el problema,
¿no?");
}
}
}
La clase System.Exception tiene algunas propiedades muy útiles de las que cabe destacar:
// exception4.cs
using System;
class Prueba
{
public static void Main()
{
int v0 = 0;
int v1 = 1;
try
{
v1 = v1 / v0;
}
catch (DivideByZeroException exception)
{
Console.WriteLine("exception.Message: {0}", exception.Message);
Console.WriteLine("exception.StackTrace: {0}",
exception.StackTrace);
}
finally
{
Console.WriteLine("¡Ya eres un experto en manejo de excepciones!");
}
}
}