Introducción al lenguaje C#
La sintaxis
1. Los identificadores
Los identificadores son los nombres que se asignan a las clases y a sus miembros. Un identificador debe estar compuesto por una única palabra. Ésta debe empezar por una letra o un carácter underscore (_). Los identificadores pueden tener letras mayúsculas o minúsculas, pero como el lenguaje C# es sensible a mayúsculas/minúsculas, éstas se deben respetar para que la referencia al identificador sea correcta: miIdentificador es diferente a MiIdentificador.
2. Las palabras clave
Las palabras clave son los nombres que reserva el lenguaje C#. Se interpretan por el compilador y, por tanto, no se pueden usar como identificadores. Estas palabras clave se diferencian en el editor de texto de Visual Studio utilizando el color azul (con los argumentos de apariencia predeterminados).
Si necesita utilizar una palabra clave como un identificador para un miembro, es necesario utilizar un prefijo con el nombre del identificador: el carácter @. La siguiente sintaxis es errónea y el compilador no la podrá ejecutar:
private bool lock;
Si utilizamos el prefijo @ con el miembro lock, el compilador considera que es un identificador y no una palabra clave:
private bool @lock;
El carácter @ también puede servir como prefijo de los identificadores que no tienen ningún conflicto con las palabras claves, de esta manera @miIdentificador se interpretará de la misma manera que miIdentificador.
A continuación, se muestra una lista de las palabras clave del lenguaje C#. Se explicarán, en parte, a lo largo del libro:
abstract |
add |
as |
ascending |
async |
await |
base |
bool |
break |
by |
byte |
case |
catch |
char |
checked |
class |
const |
continue |
decimal |
default |
delegate |
descending |
do |
double |
dynamic |
else |
equals |
enum |
event |
explicit |
extern |
false |
finally |
fixed |
float |
for |
foreach |
from |
get |
global |
goto |
group |
if |
implicit |
in |
int |
interfaz |
internal |
into |
is |
join |
let |
lock |
long |
nameof |
namespace |
new |
null |
object |
on |
operator |
orderby |
out |
override |
params |
partial |
private |
protected |
public |
readonly |
ref |
remove |
return |
sbyte |
sealed |
select |
set |
short |
sizeof |
stackalloc |
static |
string |
struct |
switch |
this |
throw |
true |
try |
typeof |
uint |
ulong |
unchecked |
unsafe |
ushort |
using |
value |
var |
virtual |
volatile |
void |
where |
while |
yield |
|
|
3. Las reglas de puntuación
El objetivo de las reglas de puntuación es separar las instrucciones del programa de manera lógica, comprensible por el ser humano...
Los espacios de nombres
Los espacios de nombres permiten organizar y jerarquizar los tipos. Un espacio de nombres puede estar formado por varias clases escritas en diferentes archivos y compilados en diferentes librerías. Es el caso del Framework .NET, que reagrupa una multitud de tipos organizados en los espacios de nombres.
1. Declarar un espacio de nombres
Para añadir una clase a un espacio de nombres, enciérrela usando la palabra clave namespace seguida del nombre del espacio de nombres deseado:
namespace MiEspacio
{
class MiClaseA { }
class MiClaseB { }
}
También es posible declarar el espacio de nombres para todos los tipos de un archivo especificándolo con el alcance del archivo como sigue:
namespace MiEspacio;
class MiClaseA { }
class MiClaseB { }
Ambas notaciones producirán el mismo resultado en el momento de compilar.
2. La palabra clave using
Para acceder a un tipo, es suficiente con indicar su nombre en la jerarquía de espacios de nombres. De esta manera, para instanciar un objeto Form, será necesario escribir:
System.Windows.Forms.Form F = new System.Windows.Forms.Form();
Esta notación puede resultar algo incómoda, motivo por el que la palabra clave using permite especificar los espacios de nombres...
Los tipos básicos
Los tipos de datos permiten almacenar valores en la aplicación. Los lenguajes .NET son fuertemente tipados, por lo que no siempre es posible convertir un tipo de datos en un otro. Las conversiones, implícitas o explícitas, permiten convertir los tipos de datos. Esto es posible porque todos los tipos del Framework .NET provienen del tipo Object, que es el tipo básico del resto de tipos.
1. Los tipos numéricos
Los tipos numéricos se dividen en dos grupos: los enteros y los decimales. Cada uno tiene un conjunto de tipos para representar los datos de la mejor manera, en función de las necesidades.
a. Los enteros
La siguiente tabla resume los tipos enteros disponibles en el Framework .NET:
Tipo .NET |
Nombre C# |
Descripción |
Rango de valores |
System.Byte |
byte |
Entero sin signo de 8 bits |
De 0 a 255 |
System.Int16 |
short |
Entero con signo de 16 bits |
De -32 768 a 32 767 |
System.Int32 |
int |
Entero con signo de 32 bits |
De -2 147 483 648 a 2 147 483 647 |
System.Int64 |
long |
Entero con signo de 64 bits |
De -9 223 372 036 854 775 808 a 9 223 372 036 854 775 807 |
System.SByte |
sbyte |
Entero con signo de 8 bits |
De -128 a 127 |
System.UInt16 |
ushort |
Entero sin signo de 16 bits |
De 0 a 65 535 |
System.UInt32 |
uint |
Entero sin signo de 32 bits |
De 0 a 4 294 967 295 |
System.UInt64 |
ulong |
Entero sin signo de 64 bits |
De 0 a 18 446 744 073 709 551 615 |
Un valor se puede asignar a un entero con una notación decimal:
int i = 2; // Notación decimal
Se puede usar también la notación hexadecimal y se debe preceder del prefijo 0x:
int i = 0x4B; // Notación hexadecimal equivalente: i = 75;
También está a disposición la notación binaria y debe estar precedida del prefijo 0b:
int i = 0b1101; // Notación binaria equivalente: i = 13;
Para facilitar la lectura del código, el carácter _ se puede usar como separador:
int i = 100_000_000; // Notación binaria equivalente:
i = 100000000;
b. Los decimales
La siguiente tabla resume los tipos decimales disponibles en el Framework .NET:
Tipo .NET |
Nombre C# |
Descripción |
Precisión |
System.Single |
float |
Número con coma flotante de 32 bits |
7 cifras significativas |
System.Double |
double |
Número con coma flotante de 64 bits |
15 cifras significativas |
System.Decimal... |
Las constantes y las enumeraciones
Las constantes son variables que no se pueden modificar durante la ejecución. Permiten, por una parte, asociar nombres amigables a los valores que se usan frecuentemente en el código y, por otra parte, centralizar un valor de manera que solo se pueda modificar una única vez para toda la aplicación. Las enumeraciones son un conjunto de constantes que facilitan la legibilidad y el mantenimiento del código.
1. Las constantes
La palabra clave const permite definir una constante dentro de una clase:
class MiClase
{
const int HorasDelDia = 24;
}
Las constantes pueden ser de cualquier tipo, por valor o string, que representan valores fijos que no se pueden modificar durante la ejecución del programa.
Una constante se puede usar en el código, haciendo referencia a su nombre:
int i = HorasDelDia; // i = 24
Según su nivel de acceso, una constante también se puede usar fuera de la clase en la que se define y ser llamada como miembro estático:
int i = MiClase.HorasDelDia; // i = 24
2. Las enumeraciones
Las enumeraciones permiten agrupar constantes semánticamente relacionadas:
enum DiaSemana
{
Lunes,
Martes,
Miércoles, ...
Los arrays
Los arrays (matrices) permiten agrupar series de variables y acceder a ellos usando un índice, empezando en 0. Los arrays pueden tener una o varias dimensiones.
La declaración de un array se hace añadiendo [] al tipo de datos que se almacenará y su inicialización se hace indicando el número máximo de elementos que puede contener:
int[] Array;
Array = new int[10];
La declaración e inicialización se pueden hacer en una única instrucción:
int[] Array = new int[10];
El array declarado en el código anterior podrá contener 10 elementos de tipo int y tendrá un índice comprendido entre 0 y 9.
Es posible inicializar un array sin especificar el límite máximo, sino especificando una serie de valores. Se indican entre llaves y separados por comas:
int[] Array = new int[] { 1, 2, 5, 9, 12 };
El Framework .NET también tiene en cuenta los arrays multidimensionales. Los arrays rectangulares son arrays en los que cada registro tiene el mismo número de columnas:
int[,] Array = new int[2, 2];
int[,,] Array = new int[5, 3, 2];
Los arrays escalares son otro tipo de arrays multidimensionales. A diferencia de lo que sucede con los arrays rectangulares, los arrays escalares tienen registros que pueden tener un número de columnas diferente. Se trata de tener un array de arrays:
int[][] Array = new int[2][]; ...
Las colecciones
Una colección es un tipo especializado que organiza y expone grupos de objetos. Como sucede con los arrays, se accede a los miembros mediante un índice. La diferencia es que las colecciones son redimensionables y es posible añadir y eliminar miembros durante la ejecución.
Las colecciones se encuentran en el espacio de nombres System.Collections. Lo más común de las colecciones es el tipo ArrayList, que permite añadir y eliminar de manera dinámica elementos al final, o en un índice predeterminado:
ArrayList miColeccion = new ArrayList();
miColeccion.Add(new object());
miColeccion.Insert(0, "ABCD");
La colección de tipo ArrayList contiene objetos de tipo object. Es posible añadir varios tipos de objeto diferentes. Esto implica que durante la recuperación el objeto se debe convertir explícitamente:
string s = (string)miColeccion[0];
El principal interés de las colecciones es poder realizar un bucle sobre todos los miembros, gracias a la instrucción foreach:
foreach (object o in miColeccion)
{}
Cuando se utiliza esta sintaxis, es preciso asegurar que todos los miembros tienen el mismo tipo que la variable de iteración. Si no es así, el cuerpo del bucle debe tener un proceso para comprobar el tipo del objeto:
foreach (object o in miColeccion)
{
...
Las directivas preprocesador
Las directivas preprocesador dan al compilador información adicional relacionada con las secciones del código. Las directivas más comunes son las directivas condicionales, que permiten incluir o no algunas secciones durante la compilación.
Las directivas se definen en las propiedades del proyecto (menú Proyecto - Propiedades de SelfMailer...) en la pestaña Compilar, en la sección General:
De manera predeterminada, Visual Studio genera dos símbolos DEBUG y TRACE en modo de compilación Debug, y solo TRACE en modo Release. Es posible no administrar esos símbolos si no se especifican o añadir personalizados en el campo Símbolos de compilación condicional.
El ejemplo siguiente comprueba si está definida la constante DEBUG para poder ejecutar el código:
class MiClase
{
int i;
public void MiMetodo()
{
#if DEBUG
MessageBox.Show("i = " + i.ToString());
#endif
}
}
Si se define la constante DEBUG en el momento de la compilación, se compilará el código que permite mostrar un cuadro de diálogo con el valor de la variable i.
La tabla siguiente resume las directivas de preprocesador:
Directiva preprocesador... |