C#
Introducción
e información general
Historia
C#
es el lenguaje orientado a objetos diseñado por Microsoft para su plataforma
.NET.
Sus
principales creadores son Scott Wiltamuth y Anders Hejlsberg, éste último
también
Conocido por
haber sido el diseñador del lenguaje Turbo Pascal y la herramienta RAD
Delphi.
Apareció en: 2001. Sistema operativo: multiplataforma. C# combina los mejores
Elementos de
múltiples lenguajes de amplia difusión como C++, Java, Visual Basic o
Delphi.
El nombre C Sharp fue inspirado
por la notación musical, donde ♯ indica que la nota es
un
semitono más alta, sugiriendo que C♯ es superior a C/C++. C♯, como parte de la
plataforma.NET, está normalizado por ECMA
desde diciembre de 2001.
Estructura básica
Los programas en C# pueden constar de uno o
varios archivos. Cada
archivo puede
contener cero o varios espacios de nombres. Un espacio de nombres puede contener tipos como
clases, structs, interfaces, enumeraciones y
delegados, además de otros espacios de nombres. A
continuación, se muestra el esqueleto de un
programa en C# que contiene todos estos elementos.
using System;
namespace
YourNamespace
{
class YourClass
{
}
struct
YourStruct
{
}
interface
IYourInterface
{
}
delegate int
YourDelegate();
enum YourEnum
{
}
namespace
YourNestedNamespace
{
struct
YourStruct
{
}
}
class
YourMainClass
{
static void Main(string[]
args)
{
//Your program starts here...
}
}
}
Clase
Una clase es una construcción que permite crear tipos
personalizados propios mediante
la agrupación de variables de otros tipos,
métodos y eventos. Una clase
es como un plano.
Define los datos y el comportamiento de un
tipo. Si la clase no se declara como estática, el
código de cliente puede utilizarla mediante la
creación de objetos o instancias que se asignan a
una variable. La variable permanece en memoria hasta que
todas las referencias a ella están fuera
del ámbito. En ese momento, CLR la marca como apta para la recolección
de elementos no
utilizados.
puede tener acceso a ella a través de la propia
clase y no de una variable
de instancia.
Aunque se
utilizan a veces de forma intercambiable, una clase y un objeto son cosas
diferentes.
Una clase
define un tipo de objeto, pero no es propiamente un objeto. Un objeto es
una entidad concreta
basada en una clase y, a veces, se denomina instancia de una clase.
basará el objeto, de
la manera siguiente:
C#
Customer object1 = new Customer();
Cuando
se crea una instancia de una clase, una referencia al objeto se vuelve a pasar
al
programador. En
el ejemplo anterior, object1 es una referencia a un objeto basado
en Customer. Esta referencia apunta al nuevo
objeto, pero no contiene los datos del objeto. De
hecho,
se puede crear una referencia a objeto sin crear un objeto:
C#
Customer object2;
No se
recomienda crear este tipo de referencias que realmente no apuntan a un objeto
existente,
ya que
al intentar el acceso a un objeto a través de esa referencia se producirá un
error en tiempo
de
ejecución. No obstante, este tipo de referencia se puede crear para hacer
referencia a un
objeto,
ya sea creando un nuevo objeto o asignándola a un objeto existente, de la forma
siguiente:
C#
Customer object3 = new Customer();
Customer object4 = object3;
Este
código crea dos referencias a objeto que se refieren al mismo objeto. Por
consiguiente, los
cambios realizados en el objeto a través de object3 se reflejarán en
los usos
posteriores
de object4. Puesto que el acceso a los objetos basados en clases se
realiza por
referencia, las
clases se denominan tipos por referencia.
La
herencia se realiza a través de una derivación, lo que significa
que una clase se declara
utilizando
una clase base de la cual hereda los datos y el
comportamiento. Una clase base se
especifica
anexando dos puntos y el nombre de la clase base a continuación del nombre de
la
clase
derivada, del modo siguiente:
C#
public class Manager : Employee
{
// Employee fields, properties, methods and events
are inherited
// New Manager fields, properties, methods and
events go here...
}
Cuando
una clase declara una clase base, hereda todos los miembros de la clase base
excepto los
constructores.
A
diferencia de C++, una clase en C# solo puede heredar directamente de una clase
base. Sin
embargo,
dado que una clase base puede heredar de otra clase, una clase puede heredar
indirectamente
de varias clases base. Además, una clase puede implementar directamente
más de
incluyen
una definición de firma pero ninguna implementación. No se pueden crear
instancias de
las clases abstractas. Solo se pueden
utilizar a través de clases derivadas que implementan los
ella. Para
obtener más información, vea Clases
y miembros de clase abstractos y sellados (Guía de programación de C#).
Las
definiciones de clase se pueden dividir entre archivos de código fuente
diferentes. Para
En el
ejemplo siguiente, se define una clase pública que contiene un campo único, un
método y
un
método especial denominado constructor. Para obtener más información,
vea Constructores
(Guía de programación de C#). Luego se crean instancias de la clase con la palabra clave new.
C#
public class Person
{
// Field
public string name;
// Constructor that takes no arguments.
public Person()
{
name = "unknown";
}
// Constructor that takes one argument.
public Person(string nm)
{
name = nm;
}
// Method
public void SetName(string newName)
{
name = newName;
}
}
class TestPerson
{
static void Main()
{
// Call the constructor that has
no parameters.
Person person1 = new Person();
Console.WriteLine(person1.name);
person1.SetName("John
Smith");
Console.WriteLine(person1.name);
// Call the constructor that has
one parameter.
Person person2 = new Person("Sarah
Jones");
Console.WriteLine(person2.name);
// Keep the console window open
in debug mode.
Console.WriteLine("Press any key
to exit.");
Console.ReadKey();
}
}
// Output:
// unknown
// John Smith
// Sarah Jones
Librerías
Comandos consola
tienen las clases de
“System.Diagnostics” y en particular la clase “Process”, que permite realizar
llamadas a Procesos externos.
Para este ejemplo voy a crear una
aplicación muy simple llamada CMD Executer que su única
función es ejecutar comandos CMD.
Primero vamos a crear una clase
estática llamada “ExecuteCommand” que recibe como
parámetro un comando como cadena de
texto:
static void ExecuteCommand(string _Command)
{
//Indicamos que deseamos inicializar el proceso cmd.exe junto a un comando de arranque.
//(/C, le indicamos al proceso cmd que deseamos que cuando termine la tarea asignada se cierre el proceso).
//Para mas informacion consulte la ayuda de la consola con cmd.exe /?
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + _Command);
// Indicamos que la salida del proceso se redireccione en un Stream
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
//Indica que el proceso no despliegue una pantalla negra (El proceso se ejecuta en background)
procStartInfo.CreateNoWindow = false;
//Inicializa el proceso
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
//Consigue la salida de la Consola(Stream) y devuelve una cadena de texto
string result = proc.StandardOutput.ReadToEnd();
//Muestra en pantalla la salida del Comando
Console.WriteLine(result);
}
Nuestro siguiente paso, para que
parezca una consola verdadera es crear un ciclo while infinito, que se detenga
cuando ingresemos el comando “Salir”:
static void Main(string[] args)
{
string command = "dir";
Console.WriteLine("CMD Executer V.0.1");
Console.WriteLine("Last Release 05 - Febraury - 2012");
while (true)
{
Console.Write("#:");
command = Console.ReadLine();
if (command == "Salir" || command == "salir")
{
break;
}
ExecuteCommand(command);
}
}
Captura y Lectura de datos
Las propiedades
proporcionan la comodidad de utilizar miembros de datos públicos sin los
riesgos que implica el
acceso no protegido y sin control ni comprobación a los datos de un
objeto. Esto se logra a través de
los descriptores de acceso: métodos especiales que
asignan y
de datos.
Este ejemplo muestra una
clase Person con dos propiedades: Name (cadena)
y Age (entero). Ambas propiedades proporcionan
descriptores de acceso get y set, por lo que se
consideran propiedades de
lectura y escritura.
Ejemplo
C#
class Person
{
private string name = "N/A";
private int age = 0;
// Declare a Name property of type string:
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
// Declare an Age property of type int:
public int Age
{
get
{
return age;
}
set
{
age = value;
}
}
public override string ToString()
{
return "Name = " + Name + ", Age = " + Age;
}
}
class TestPerson
{
static void Main()
{
// Create a new Person object:
Person person = new Person();
// Print out the name and the age associated with the person:
Console.WriteLine("Person details - {0}", person);
// Set some values on the person object:
person.Name = "Joe";
person.Age = 99;
Console.WriteLine("Person details - {0}", person);
// Increment the Age property:
person.Age += 1;
Console.WriteLine("Person details - {0}", person);
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
Person details - Name = N/A, Age = 0
Person details - Name = Joe, Age = 99
Person details - Name = Joe, Age = 100
*/
Estructuras repetitivas
Hemos visto cómo comprobar
condiciones, pero no cómo hacer que una cierta parte de un programa se repita
un cierto número de veces o mientras se cumpla una condición (lo que llamaremos
un "bucle"). En C# tenemos varias formas de conseguirlo.
While
Si queremos hacer que una
sección de nuestro programa se repita mientras se cumpla una cierta condición,
usaremos la orden "while". Esta orden tiene dos formatos distintos,
según comprobemos la condición al principio o al final.
En el primer caso, su
sintaxis es:
while (condición)
sentencia;
Es decir, la sentencia se
repetirá mientras la condición sea cierta. Si la condición es falsa ya desde un
principio, la sentencia no se ejecuta nunca. Si queremos que se repita más de
una sentencia, basta agruparlas entre { y }.
Un ejemplo que nos diga si
cada número que tecleemos es positivo o negativo, y que pare cuando tecleemos
el número 0, podría ser:
/*---------------------------*/
/* Ejemplo en C# nº 22: */
/* ejemplo22.cs */
/* */
/* La orden "while" */
/* */
/* Introduccion a C#, */
/* Nacho Cabanes */
/*---------------------------*/
using System;
public class Ejemplo22
{
public static void Main()
{
int numero;
Console.Write("Teclea un número (0 para salir): ");
numero = Convert.ToInt32(Console.ReadLine());
while (numero != 0)
{
if (numero > 0) Console.WriteLine("Es positivo");
else Console.WriteLine("Es negativo");
Console.WriteLine("Teclea otro número (0 para salir): ");
numero = Convert.ToInt32(Console.ReadLine());
}
}
}
En este ejemplo, si se
introduce 0 la primera vez, la condición es falsa y ni siquiera se entra al
bloque del "while", terminando el programa inmediatamente.
Do while
Este es el otro formato que
puede tener la orden "while": la condición se comprueba al final. El
punto en que comienza a repetirse se indica con la orden "do", así:
do
sentencia;
while (condición);
Al igual que en el caso
anterior, si queremos que se repitan varias órdenes (es lo habitual), deberemos
encerrarlas entre llaves.
Como ejemplo, vamos a ver
cómo sería el típico programa que nos pide una clave de acceso y no nos deja
entrar hasta que tecleemos la clave correcta:
/*---------------------------*/
/* Ejemplo en C# nº 23: */
/* ejemplo23.cs */
/* */
/* La orden "do..while" */
/* */
/* Introduccion a C#, */
/* Nacho Cabanes */
/*---------------------------*/
using System;
public class Ejemplo23
{
public static void Main()
{
int valida = 711;
int clave;
do
{
Console.Write("Introduzca su clave numérica: ");
clave = Convert.ToInt32(Console.ReadLine());
if (clave != valida) Console.WriteLine("No válida!\n");
}
while (clave != valida);
Console.WriteLine("Aceptada.\n");
}
}
En este caso, se comprueba
la condición al final, de modo que se nos preguntará la clave al menos una vez.
Mientras que la respuesta que demos no sea la correcta, se nos vuelve a preguntar.
Finalmente, cuando tecleamos la clave correcta, el ordenador escribe
"Aceptada" y termina el programa.
Si preferimos que la clave
sea un texto en vez de un número, los cambios al programa son mínimos:
/*---------------------------*/
/* Ejemplo en C# nº 24: */
/* ejemplo24.cs */
/* */
/* La orden "do..while" (2) */
/* */
/* Introduccion a C#, */
/* Nacho Cabanes */
/*---------------------------*/
using System;
public class Ejemplo24
{
public static void Main()
{
string valida = "secreto";
string clave;
do
{
Console.Write("Introduzca su clave: ");
clave = Console.ReadLine();
if (clave != valida) Console.WriteLine("No válida!\n");
}
while (clave != valida);
Console.WriteLine("Aceptada.\n");
}
}
For
Ésta es la orden que
usaremos habitualmente para crear partes del programa que se repitan un cierto
número de veces. El formato de "for" es:
for (valorInicial; CondiciónRepetición; Incremento)
Sentencia;
Así, para contar del 1 al
10, tendríamos 1 como valor inicial, <=10 como condición de repetición, y el
incremento sería de 1 en 1. Por tanto, el programa quedaría:
/*---------------------------*/
/* Ejemplo en C# nº 25: */
/* ejemplo25.cs */
/* */
/* Uso básico de "for" */
/* */
/* Introduccion a C#, */
/* Nacho Cabanes */
/*---------------------------*/
using System;
public class Ejemplo25
{
public static void Main()
{
int contador;
for (contador=1; contador<=10; contador++)
Console.Write("{0} ", contador);
}
}
Recordemos que
"contador++" es una forma abreviada de escribir
"contador=contador+1", de modo que en este ejemplo aumentamos la
variable de uno en uno.
En un "for",
realmente, la parte que hemos llamado "Incremento" no tiene por qué
incrementar la variable, aunque ése es su uso más habitual. Es simplemente una
orden que se ejecuta cuando se termine la "Sentencia" y antes de
volver a comprobar si todavía se cumple la condición de repetición.
Por eso, si escribimos la
siguiente línea:
for (contador=1; contador<=10; )
la variable
"contador" no se incrementa nunca, por lo que nunca se cumplirá la
condición de salida: nos quedamos encerrados dando vueltas dentro de la orden
que siga al "for".
Un caso todavía más
exagerado de algo a lo que se entra y de lo que no se sale sería la siguiente
orden:
for ( ; ; )
Los bucles "for"
se pueden anidar (incluir uno dentro de otro), de modo que podríamos escribir
las tablas de multiplicar del 1 al 5 con:
/*---------------------------*/
/* Ejemplo en C# nº 26: */
/* ejemplo26.cs */
/* */
/* "for" anidados */
/* */
/* Introduccion a C#, */
/* Nacho Cabanes */
/*---------------------------*/
using System;
public class Ejemplo26
{
public static void Main()
{
int tabla, numero;
for (tabla=1; tabla<=5; tabla++)
for (numero=1; numero<=10; numero++)
Console.WriteLine("{0} por {1} es {2}", tabla, numero,
tabla*numero);
}
}
En estos ejemplos que hemos
visto, después de "for" había una única sentencia. Si queremos que se
hagan varias cosas, basta definirlas como un bloque (una sentencia compuesta)
encerrándolas entre llaves. Por ejemplo, si queremos mejorar el ejemplo
anterior haciendo que deje una línea en blanco entre tabla y tabla, sería:
/*---------------------------*/
/* Ejemplo en C# nº 27: */
/* ejemplo27.cs */
/* */
/* "for" anidados (2) */
/* */
/* Introduccion a C#, */
/* Nacho Cabanes */
/*---------------------------*/
using System;
public class Ejemplo27
{
public static void Main()
{
int tabla, numero;
for (tabla=1; tabla<=5; tabla++)
{
for (numero=1; numero<=10; numero++)
Console.WriteLine("{0} por {1} es {2}", tabla, numero,
tabla*numero);
Console.WriteLine();
}
}
}
Para "contar" no
necesariamente hay que usar números. Por ejemplo, podemos contar con letras
así:
/*---------------------------*/
/* Ejemplo en C# nº 28: */
/* ejemplo28.cs */
/* */
/* "for" que usa "char" */
/* */
/* Introduccion a C#, */
/* Nacho Cabanes */
/*---------------------------*/
using System;
public class Ejemplo28
{
public static void Main()
{
char letra;
for (letra='a'; letra<='z'; letra++)
Console.Write("{0} ", letra);
}
}
En este caso, empezamos en
la "a" y terminamos en la "z", aumentando de uno en uno.
Si queremos contar de forma
decreciente, o de dos en dos, o como nos interese, basta indicarlo en la
condición de finalización del "for" y en la parte que lo incrementa:
/*---------------------------*/
/* Ejemplo en C# nº 29: */
/* ejemplo29.cs */
/* */
/* "for" que descuenta */
/* */
/* Introduccion a C#, */
/* Nacho Cabanes */
/*---------------------------*/
using System;
public class Ejemplo29
{
public static void Main()
{
char letra;
for (letra='z'; letra>='a'; letra--)
Console.Write("{0} ", letra);
}
}
Estructura condicional
Una instrucción if identifica que sentencia
se tiene que ejecutar en función del valor de una expresión Boolean. En el ejemplo siguiente,
la variable Booleanresult se establece en true y, a continuación, se
comprueba en la instrucción if. La
salida es The
condition is true.
C#
bool condition = true;
if (condition)
{
Console.WriteLine("The variable is set to true.");
}
else
{
Console.WriteLine("The variable is set to false.");
}
Puede ejecutar los
ejemplos de este tema colocándolos en el método de Main de una aplicación de
consola.
Una instrucción if en C# puede tomar dos
formas, como se muestra en el ejemplo siguiente.
C#
// if-else statement
if (condition)
{
then-statement;
}
else
{
else-statement;
}
// Next statement in the program.
// if statement without an else
if (condition)
{
then-statement;
}
// Next statement in the program.
En una instrucción if-else, si la condición se evalúa como true, se ejecuta la sentencia then-statement. Si condition es false, else-statement ejecuta. Dado que la condición
(condition) no puede ser simultáneamente verdadera (true)
y falsa (false), las sentencias then-statement y else-statement de una instrucción if-else nunca pueden ejecutarse
simultáneamente. Después de then-statement o de las ejecuciones de else-statement, el control se
transfiere a la instrucción siguiente después de la instrucción de if.
En una instrucción de if que no incluya una
instrucción de else, si condition es true, then-statement ejecuta. Si condition es false, el control se
transfiere a la instrucción siguiente después de la instrucción de if.
then-statement y else-statement pueden constar de una
sola instrucción o varias instrucciones que se agrega entre llaves ({}). Para una sola
instrucción, las llaves son opcionales pero recomendados.
La instrucción o
instrucciones en then-statement y else-statement puede ser de clase,
incluso otra instrucción de if anidada dentro de la
instrucción original de if. En instrucciones anidadas
de if, cada cláusula de else pertenece a if último que no tiene else correspondiente. En el ejemplo siguiente, Result1 aparece si m > 10 y n > 20 se evalúan como true. Si m > 10 es true pero n > 20 es false, Result2 aparece.
C#
// Try with m = 12 and then with m = 8.
int m = 12;
int n = 18;
if (m > 10)
if (n > 20)
{
Console.WriteLine("Result1");
}
else
{
Console.WriteLine("Result2");
}
Si, en su lugar, se desea
que Result2 aparezca cuando (m > 10) es false, puede
especificar que la asociación mediante las llaves para establecer el inicio y
el final de la instrucción anidada de if, como se muestra en el
ejemplo siguiente.
C#
// Try with m = 12 and then with m = 8.
if (m > 10)
{
if (n > 20)
Console.WriteLine("Result1");
}
else
{
Console.WriteLine("Result2");
}
Result2 aparece si la condición (m > 10) evalúa en false.
Ejemplo
En el ejemplo siguiente,
se escribe un carácter de teclado, y el programa utiliza una instrucción anidada
de if para determinar si el
carácter de entrada es un carácter alfabético.Si el carácter de entrada es un
carácter alfabético, el programa comprueba si el carácter se introdujo en
minúsculas o en mayúsculas. Aparecerá un mensaje para cada caso.
C#
Console.Write("Enter a character: ");
char c = (char)Console.Read();
if (Char.IsLetter(c))
{
if (Char.IsLower(c))
{
Console.WriteLine("The character is lowercase.");
}
else
{
Console.WriteLine("The character is uppercase.");
}
}
else
{
Console.WriteLine("The character isn't an alphabetic character.");
}
//Sample Output:
//Enter a character: 2
//The character isn't an alphabetic character.
//Enter a character: A
//The character is uppercase.
//Enter a character: h
//The character is lowercase.
También puede anidar una
instrucción de if dentro de un bloque else,
como el código parcial siguiente. Las instrucciones de if de los nidos de ejemplo
desde dos bloques otros y una continuación bloqueada. Los comentarios
especifican qué condiciones son true o false en cada bloque.
C#
// Change the values of these variables to test the results.
bool Condition1 = true;
bool Condition2 = true;
bool Condition3 = true;
bool Condition4 = true;
if (Condition1)
{
// Condition1 is true.
}
else if (Condition2)
{
// Condition1 is false and Condition2 is true.
}
else if (Condition3)
{
if (Condition4)
{
// Condition1 and Condition2 are false. Condition3 and Condition4 are true.
}
else
{
// Condition1, Condition2, and Condition4 are false. Condition3 is true.
}
}
else
{
// Condition1, Condition2, and Condition3 are false.
}
El ejemplo siguiente
determina si un carácter de entrada es una minúscula, una letra mayúscula, o un
número. Si las tres condiciones son false, el carácter
no es un carácter alfanumérico. El ejemplo muestra un mensaje para cada caso.
C#
Console.Write("Enter a character: ");
char ch = (char)Console.Read();
if (Char.IsUpper(ch))
{
Console.WriteLine("The character is an uppercase letter.");
}
else if (Char.IsLower(ch))
{
Console.WriteLine("The character is a lowercase letter.");
}
else if (Char.IsDigit(ch))
{
Console.WriteLine("The character is a number.");
}
else
{
Console.WriteLine("The character is not alphanumeric.");
}
//Sample Input and Output:
//Enter a character: E
//The character is an uppercase letter.
//Enter a character: e
//The character is a lowercase letter.
//Enter a character: 4
//The character is a number.
//Enter a character: =
//The character is not alphanumeric.
Igual que una instrucción
del bloque else o el bloque then puede ser cualquier instrucción válida, puede
utilizar cualquier expresión booleana válida para la condición. Puede usar operadores
lógicos como &&, y, ||, |y ! para crear condiciones
compuestas. El código siguiente muestra ejemplos.
C#
// NOT
bool result = true;
if (!result)
{
Console.WriteLine("The condition is true (result is false).");
}
else
{
Console.WriteLine("The condition is false (result is true).");
}
// Short-circuit AND
int m = 9;
int n = 7;
int p = 5;
if (m >= n && m >= p)
{
Console.WriteLine("Nothing is larger than m.");
}
// AND and NOT
if (m >= n && !(p > m))
{
Console.WriteLine("Nothing is larger than m.");
}
// Short-circuit OR
if (m > n || m > p)
{
Console.WriteLine("m isn't the smallest.");
}
// NOT and OR
m = 4;
if (!(m >= n || m >= p))
{
Console.WriteLine("Now m is the smallest.");
}
// Output:
// The condition is false (result is true).
// Nothing is larger than m.
// Nothing is larger than m.
// m isn't the smallest.
// Now m is the smallest.
Matrices en general
En las matrices de C#, los índices empiezan en
cero. Las matrices de C# funcionan de forma similar a como lo hacen en la
mayoría de los lenguajes populares; existen, sin embargo, algunas diferencias
que se deben conocer.
Cuando se declara una matriz, los corchetes
([]) deben ir después del tipo, no después del identificador. Colocar los
corchetes después del identificador no es sintácticamente válido en
C#.
int[] table; // not int table[];
Otro detalle es que el tamaño de la matriz no
forma parte de su tipo, como ocurre en el lenguaje C. Esto permite declarar una
matriz y asignarle cualquier matriz de objetos int, independientemente de la
longitud de la matriz.
int[] numbers; // declare numbers as an int array of any size
numbers = new int[10]; // numbers is a 10-element array
numbers = new int[20]; // now it's a 20-element array
Declarar matrices
C# admite matrices de una dimensión, matrices
multidimensionales (matrices rectangulares) y matrices de matrices (matrices escalonadas).
El siguiente ejemplo muestra cómo declarar diferentes tipos de matrices:
Matrices
unidimensionales:
int[] numbers;
Matrices multidimensionales:
string[,] names;
Matrices de matrices (escalonadas):
byte[][] scores;
La declaración de matrices (como se muestra
arriba) no crea realmente las matrices. En C#, las matrices son objetos (se
explica más adelante en este tutorial) cuyas instancias deben crearse. Los
siguientes ejemplos muestran cómo crear matrices:
Matrices unidimensionales:
int[] numbers = new int[5];
Matrices multidimensionales:
string[,] names = new string[5,4];
Matrices de matrices (escalonadas):
byte[][] scores = new byte[5][];
for (int x = 0; x < scores.Length; x++)
{
scores[x] = new byte[4];
}
También se pueden utilizar matrices más grandes. Por ejemplo, se
puede utilizar una matriz rectangular de tres dimensiones:
int[,,] buttons = new int[4,5,3];
Incluso, se pueden combinar matrices
rectangulares y escalonadas. Por ejemplo, el siguiente código declara una matriz
unidimensional que contiene matrices tridimensionales de matrices
bidimensionales de tipo int:
int[][,,][,] numbers;
Ejemplo
El siguiente es un programa completo en C# que
declara y crea instancias de las matrices comentadas anteriormente.
// arrays.cs
using System;
class DeclareArraysSample
{
public static void Main()
{
// Single-dimensional array
int[] numbers = new int[5];
// Multidimensional array
string[,] names = new string[5,4];
// Array-of-arrays (jagged array)
byte[][] scores = new byte[5][];
// Create the jagged array
for (int i = 0; i < scores.Length; i++)
{
scores[i] = new byte[i+3];
}
// Print length of each row
for (int i = 0; i < scores.Length; i++)
{
Console.WriteLine("Length of row {0} is {1}", i, scores[i].Length);
}
}
}
Resultado
Length of row 0 is 3
Length of row 1 is 4
Length of row 2 is 5
Length of row 3 is 6
Length of row 4 is 7
Inicializar matrices
C# proporciona métodos simples y sencillos
para inicializar matrices en el momento de la declaración encerrando los
valores iniciales entre llaves ({}). Los siguientes ejemplos muestran
diferentes modos de inicializar diferentes tipos de matrices.
Nota Si no inicializa una matriz en el momento de la
declaración, sus miembros se inicializan automáticamente con el valor inicial
predeterminado para el tipo de matriz. Además, si declara la matriz como campo
de un tipo, se establecerá con el valor predeterminado null cuando cree la
instancia del tipo.
Matrices
unidimensionales
int[] numbers = new int[5] {1, 2, 3, 4, 5};
string[] names = new string[3] {"Matt", "Joanne", "Robert"};
El tamaño de la matriz se puede omitir, como
se indica a continuación:
int[] numbers = new int[] {1, 2, 3, 4, 5};
string[] names = new string[] {"Matt", "Joanne", "Robert"};
También se puede omitir el operador new si se utiliza un inicializador como el
siguiente:
int[] numbers = {1, 2, 3, 4, 5};
string[] names = {"Matt", "Joanne", "Robert"};
Matrices
multidimensionales
int[,] numbers = new int[3, 2] { {1, 2}, {3, 4}, {5, 6} };
string[,] siblings = new string[2, 2] { {"Mike","Amy"}, {"Mary","Albert"} };
El tamaño de la matriz se puede omitir, como
se indica a continuación:
int[,] numbers = new int[,] { {1, 2}, {3, 4}, {5, 6} };
string[,] siblings = new string[,] { {"Mike","Amy"}, {"Mary","Albert"} };
También se puede omitir el operador new si se utiliza un inicializador como el
siguiente:
int[,] numbers = { {1, 2}, {3, 4}, {5, 6} };
string[,] siblings = { {"Mike", "Amy"}, {"Mary", "Albert"} };
Matriz
escalonada (matriz de matrices)
Las matrices escalonadas se pueden inicializar
como en el siguiente ejemplo:
int[][] numbers = new int[2][] { new int[] {2,3,4}, new int[] {5,6,7,8,9} };
El tamaño de la primera matriz se puede
omitir, como se indica a continuación:
int[][] numbers = new int[][] { new int[] {2,3,4}, new int[] {5,6,7,8,9} };
O bien
int[][] numbers = { new int[] {2,3,4}, new int[] {5,6,7,8,9} };
Observe que no existe sintaxis de
inicialización para los elementos de una matriz escalonada.
Acceso a miembros de matrices
El acceso a los miembros de una matriz es
sencillo y similar al de los miembros de una matriz de C o C++. Por ejemplo, el
siguiente código crea una matriz denominada numbers
y, a
continuación, asigna un 5
al quinto elemento de la matriz:
int[] numbers = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
numbers[4] = 5;
El siguiente código declara una matriz
multidimensional y asigna el valor 5
al miembro ubicado en [1, 1]
:
int[,] numbers = { {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10} };
numbers[1, 1] = 5;
La siguiente es una declaración de una matriz
escalonada de una sola dimensión que contiene dos elementos. El primer elemento
es una matriz de dos enteros, mientras que el segundo es una matriz de tres
enteros:
int[][] numbers = new int[][] { new int[] {1, 2}, new int[] {3, 4, 5}
};
La siguiente instrucción asigna 58 al primer
elemento de la primera matriz y 667 al segundo elemento de la segunda matriz:
numbers[0][0] = 58;
numbers[1][1] = 667;
numbers
y, a
continuación, asigna un 5
al quinto elemento de la matriz:5
al miembro ubicado en [1, 1]
:
Las matrices son objetos
En C#, las matrices son realmente objetos. System.Array es el tipo base abstracto de todos los
tipos de matrices. Las propiedades y otros miembros de la clase System.Array se pueden utilizar cuando sea
necesario. Un ejemplo de esto sería utilizar la propiedad Length para obtener la longitud de una
matriz. El siguiente código asigna la longitud de la matriz numbers
,
que es 5
, a una
variable denominada LengthOfNumbers
:
int[] numbers = {1, 2, 3, 4, 5};
int LengthOfNumbers = numbers.Length;
La clase System.Array proporciona muchos otros métodos y
propiedades útiles, como métodos para ordenar, buscar y copiar matrices.
numbers
,
que es 5
, a una
variable denominada LengthOfNumbers
:
Usar foreach con matrices
C# dispone de la instrucción foreach. Esta instrucción
proporciona un modo simple y limpio de iterar en los elementos de una matriz.
Por ejemplo, el siguiente código crea una matriz denominada numbers
y la recorre mediante la instrucción foreach:
int[] numbers = {4, 5, 6, 1, 2, 3, -2, -1, 0};
foreach (int i in numbers)
{
System.Console.WriteLine(i);
}
Con matrices multidimensionales, se puede
utilizar el mismo método para recorrer los elementos, por ejemplo:
int[,] numbers = new int[3, 2] {{9, 99}, {3, 33}, {5, 55}};
foreach(int i in numbers)
{
Console.Write("{0} ", i);
}
El resultado de este ejemplo es:
9 99 3 33 5 55
Conexion a base de datos
La conexión a un origen de datos se realiza
fácilmente con Visual C# Express. Puede utilizar herramientas visuales para
buscar una base de datos y agregar una copia local al proyecto. Al instalar SQL
Server Compact 3.5 con Visual C# Express, podrá utilizar una base de datos de
ejemplo denominada Northwind.sdf. Puede conectarse a la base de datos Northwind
mediante la ventana Orígenes de datos.
numbers
y la recorre mediante la instrucción foreach:
Para agregar una conexión
a la base de datos Northwind
1.
En el
menú Archivo,
haga clic en Nuevo
proyecto.
2.
En el cuadro
de diálogo Nuevo
proyecto, haga clic en Aplicación para Windows y
luego en Aceptar.
Se
abrirá un nuevo proyecto de formularios Windows Forms.
3.
En el
menú Datos,
haga clic en Agregar
nuevo origen de datos.
Se
abrirá el Asistente
para la configuración de orígenes de datos.
4.
Haga clic
en Base de datos y, a continuación, en Siguiente.
5.
Haga clic
en Nueva conexión.
Se
abrirá el cuadro de diálogo Agregar conexión.
6.
En el
cuadro de diálogo Agregar
conexión, si el Origen de datos no
es Microsoft SQL
Server Compact 3.5 (proveedor de datos de .NET Framework para Microsoft SQL
Server Compact 3.5), haga clic en Cambiar y
seleccione Microsoft
SQL Server Compact 3.5 en
el cuadro de diálogo Cambiar origen de datos. Haga clic en Aceptar.
7.
Haga clic
en el botón Examinar y busque la base de datos
Northwind.sdf.
La
ubicación predeterminada es unidad:\Archivos de programa\Microsoft SQL Server
Compact Edition\v 3.5\Samples.
8.
Haga clic
en Probar conexión para comprobar que la conexión es
satisfactoria y, a continuación, haga clic en Aceptar para
cerrar el cuadro de diálogo.
9.
Haga clic
en Aceptar para cerrar el cuadro de diálogo y, a
continuación, en el Asistente para la configuración de orígenes de datos, haga clic
en Siguiente.
Si se le pide copiar el archivo de datos en su proyecto, haga clic en Sí.
10.
En la
página siguiente del asistente, seleccione la casilla Sí, guardar la conexión
como y, a continuación,
haga clic en Siguiente.
11.
En la
página Elija los
objetos de base de datos, expanda Tablas.
12.
Active la
casilla para Productos y Detalles del pedido y,
a continuación, haga clic en Finalizar.
Se
agrega un archivo de base de datos local al proyecto. Observe que se ha
agregado un objeto NorthwindDataSet a la ventana Orígenes de datos.
13.
En el Explorador de
soluciones, seleccione Northwind.sdf y asegúrese de que la propiedad Copiar en el directorio
de resultados presenta el
valor Copiar si es
posterior.
14.
En el
menú Archivo,
haga clic en Guardar
todo para guardar el
proyecto.
Conexión
a SQL server
Puede conectar a una base de datos de Microsoft
SQL Server utilizando el control SqlDataSource. Para ello, necesita una cadena de conexión y
derechos de acceso a una base de datos de SQL Server. A continuación, puede
utilizar el control SqlDataSource para proporcionar los datos a
cualquier control enlazado a datos que admita la propiedadDataSourceID, por ejemplo, el control GridView.
Para configurar una
cadena de conexión de SQL Server en el archivo Web.config
1.
Abra el
archivo Web.config en el directorio raíz de su aplicación ASP.NET. Si no
dispone de un archivo Web.config, cree uno.
3.
Cree un
elemento add como elemento secundario del elemento ConnectionStrings, y
defina los atributos siguientes:
o name Establezca el valor en el nombre que
desea utilizar para hacer referencia a la cadena de conexión, como en el
ejemplo siguiente.
o name="CustomerDataConnectionString"
o connectionString Asigne una cadena de
conexión con la ubicación de su SQL Server e información de autenticación, si
existe. La cadena de conexión podría parecerse a la siguiente:
o connectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind"
o providerName Asigne el valor
"System.Data.SqlClient", que especifica que ASP.NET debe utilizar el
proveedor de ADO.NET System.Data.SqlClient al realizar una conexión con esta cadena de
conexión.
La
configuración de la cadena de conexión será similar a la siguiente:
<connectionStrings>
<add name="CustomerDataConnectionString"
connectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind"
providerName="System.Data.SqlClient" />
</connectionStrings>
4.
Guarde el
archivo Web.config y ciérrelo.
Para hacer referencia a
la cadena de conexión de SQL Server desde un control SqlDataSource
1.
Agregue
un control SqlDataSource en la página en la que desea conectar
a la base de datos de SQL Server.
2.
En el
control SqlDataSource,
establezca las siguientes propiedades:
o SelectCommand Establezca el valor en una
instrucción Select de SQL para recuperar los datos, como en el ejemplo
siguiente ejemplo:
o SelectCommand="Select CustomerID, CompanyName From Customers"
o
ConnectionString Establezca el nombre de la cadena de conexión
que ha creado en el archivo Web.config con el formato <%$ ConnectionStrings:
connection string name %>
.
En el
ejemplo siguiente se muestra un control SqlDataSource configurado para establecer una
conexión con una base de datos de SQL Server.
<asp:SqlDataSource
ID="SqlDataSource1"
runat="server"
ConnectionString="<%$ ConnectionStrings:CustomerDataConnectionString %>"
SelectCommand="SELECT CustomerID, CompanyName FROM Customers" />
<%$ ConnectionStrings:
connection string name %>
.