RECURSOS DE PROGRAMACIÓN
C#: guía rápida de sintaxis
Referencia de sintaxis y conceptos habituales de C#: tipos, estructuras de control, métodos, clases y colecciones.
FUNDAMENTOS
Qué es C# y cómo se estructura un programa
C# es un lenguaje de programación moderno, fuertemente tipado y orientado a objetos. Forma parte del ecosistema .NET y se utiliza en aplicaciones web, escritorio, servicios, APIs, cloud, videojuegos y otros tipos de software.
Una de sus características principales es que los tipos tienen un papel importante desde el momento en que declaramos variables, parámetros y valores de retorno.
string nombre="Ana";
int edad=30;
double altura=1.68;
bool activo=true;En C# las instrucciones terminan habitualmente con punto y coma y los bloques se delimitan mediante llaves.
DATOS
Tipos y variables
C# dispone de distintos tipos para representar texto, números, valores lógicos y otros datos. Elegir un tipo adecuado ayuda a expresar mejor la intención del programa.
| Tipo | Ejemplo | Uso habitual |
|---|---|---|
string | "Hola" | Texto |
int | 42 | Números enteros |
long | 9000000000L | Enteros de mayor rango |
double | 3.14 | Decimales de propósito general |
decimal | 19.95m | Cálculos decimales donde importa la precisión, por ejemplo importes |
bool | true | Valores lógicos |
char | 'A' | Un carácter |
También podemos utilizar varcuando el compilador puede inferir claramente el tipo a partir del valor asignado.
var nombre="Ana";
var edad=30;varno convierte C# en un lenguaje dinámico: la variable sigue teniendo un tipo concreto determinado en tiempo de compilación.
TEXTO
Trabajar con cadenas
Las cadenas son objetos de tipo string. Podemos consultar su longitud, transformar el texto y construir mensajes dinámicos.
string lenguaje="C#"; Console.WriteLine(lenguaje.Length);
Console.WriteLine(lenguaje.ToUpper());
Console.WriteLine(lenguaje.ToLower());La interpolación de cadenas permite insertar variables de forma legible:
string nombre="Marta";
int edad=28; Console.WriteLine($"{nombre} tiene{edad} años");COLECCIONES
Arrays, List<T> y Dictionary<TKey,TValue>
Arrays
Un array almacena una cantidad fija de elementos del mismo tipo.
int[] notas={ 7, 8, 5, 9}; Console.WriteLine(notas[0]);
Console.WriteLine(notas.Length);List<T>
Una lista permite añadir y eliminar elementos dinámicamente y es una de las colecciones más utilizadas en aplicaciones .NET.
var lenguajes=new List<string>
{ "C#", "Python", "Java"}; lenguajes.Add("JavaScript"); Console.WriteLine(lenguajes.Count);Dictionary<TKey,TValue>
Los diccionarios almacenan pares clave-valor y permiten localizar información mediante una clave.
var alumno=new Dictionary<string, string>
{ ["nombre"]="Lucía", ["curso"]="Programación"}; Console.WriteLine(alumno["nombre"]);Antes de acceder directamente a una clave, conviene comprobar si existe cuando los datos pueden ser variables.
if (alumno.TryGetValue("curso", out string? curso))
{ Console.WriteLine(curso);}CONTROL DE FLUJO
Condicionales y switch
Los condicionales permiten tomar decisiones en función de una expresión lógica.
int nota=7; if (nota >=9)
{ Console.WriteLine("Sobresaliente");}
else if (nota >=5)
{ Console.WriteLine("Aprobado");}
else
{ Console.WriteLine("Suspenso");}Para múltiples casos podemos utilizar switch.
string rol = "admin";
switch (rol)
{
case "admin":
Console.WriteLine("Acceso total");
break;
case "usuario":
Console.WriteLine("Acceso limitado");
break;
default:
Console.WriteLine("Rol desconocido");
break;
}ITERACIÓN
for, foreach y while
for
forresulta útil cuando necesitamos controlar explícitamente un contador.
for (int i=0; i < 5; i++)
{ Console.WriteLine(i);}foreach
foreachresulta especialmente cómodo para recorrer colecciones.
var nombres=new List<string>{ "Ana", "Luis", "Marta"}; foreach (string nombre in nombres)
{ Console.WriteLine(nombre);}while
whilerepite un bloque mientras la condición siga siendo verdadera.
int contador=1; while (contador <=5)
{ Console.WriteLine(contador); contador++;}Conviene comprobar que la condición pueda llegar a ser falsa para evitar bucles infinitos.
REUTILIZACIÓN
Métodos
Los métodos agrupan operaciones reutilizables y permiten dividir un programa en partes más pequeñas y comprensibles.
static int Sumar(int a, int b)
{ return a + b;} int resultado=Sumar(4, 6); Console.WriteLine(resultado);Un método debería tener una responsabilidad clara y un nombre que describa la operación que realiza.
ORIENTACIÓN A OBJETOS
Clases, objetos y propiedades
Una clase define la estructura y el comportamiento de los objetos que se crean a partir de ella.
public class Alumno
{ public string Nombre{ get; set;}=""; public int Nota{ get; set;} public bool EstaAprobado() { return Nota >=5;}}Crear y utilizar un objeto:
var alumno=new Alumno
{ Nombre="Carlos", Nota=8}; Console.WriteLine(alumno.Nombre);
Console.WriteLine(alumno.EstaAprobado());INICIALIZACIÓN
Constructores
Un constructor permite definir qué datos necesita un objeto en el momento de crearlo.
public class Producto
{ public string Nombre{ get;} public decimal Precio{ get;} public Producto(string nombre, decimal precio) { Nombre=nombre; Precio=precio;}}Crear una instancia:
var producto=new Producto("Teclado", 49.95m);El constructor ayuda a impedir que el objeto nazca en un estado incompleto cuando ciertos datos son obligatorios.
ABSTRACCIÓN
Interfaces
Una interfaz define un contrato que una clase debe cumplir. Esto permite trabajar con comportamientos sin depender directamente de una implementación concreta.
public interface INotificacion
{ void Enviar(string mensaje);} public class EmailNotificacion : INotificacion
{ public void Enviar(string mensaje) { Console.WriteLine($"Email:{mensaje}");}}Las interfaces son especialmente útiles cuando distintas clases deben ofrecer una misma operación con implementaciones diferentes.
ERRORES
Manejo de excepciones
Las excepciones permiten gestionar situaciones inesperadas durante la ejecución.
try
{ int numero=int.Parse("abc");}
catch (FormatException)
{ Console.WriteLine("El valor no tiene un formato numérico válido.");}Siempre que sea posible conviene capturar excepciones concretas. Un catch (Exception)genérico puede ser necesario en determinados niveles de una aplicación, pero no debería utilizarse para ocultar errores sin tratarlos.
NULABILIDAD
Trabajar con valores nulos
C# moderno permite indicar si una referencia puede contener null. Esto ayuda a detectar posibles problemas antes de ejecutar el programa.
string? segundoNombre=null; if (segundoNombre is not null)
{ Console.WriteLine(segundoNombre.Length);}También podemos utilizar el operador de coalescencia nula:
string nombreMostrado=segundoNombre ?? "Sin segundo nombre";CONSULTAS
LINQ básico
LINQ permite consultar, filtrar, ordenar y transformar colecciones utilizando una API integrada en el ecosistema .NET.
var notas = new List<int> { 4, 8, 6, 3, 9 };
var aprobadas = notas
.Where(nota => nota >= 5)
.OrderByDescending(nota => nota)
.ToList();
foreach (int nota in aprobadas)
{
Console.WriteLine(nota);
}| Método | Uso habitual |
|---|---|
Where() | Filtrar elementos |
Select() | Transformar cada elemento |
OrderBy() | Ordenar de forma ascendente |
OrderByDescending() | Ordenar de forma descendente |
FirstOrDefault() | Obtener el primer elemento o un valor por defecto |
Any() | Comprobar si existe algún elemento que cumpla una condición |
Count() | Contar elementos |
Sum() | Sumar valores numéricos |
Average() | Calcular una media |
LINQ resulta muy potente, pero una expresión demasiado compleja puede reducir la legibilidad. Conviene priorizar consultas claras y dividirlas cuando sea necesario.
EXPRESIONES
Expresiones lambda
Las expresiones lambda permiten representar funciones breves de forma compacta. Aparecen con frecuencia en LINQ y en muchas APIs de .NET.
Func<int, int> cuadrado = numero => numero * numero;
Console.WriteLine(cuadrado(5));En una consulta LINQ:
var pares=numeros.Where(n=> n % 2==0);La parte situada a la izquierda de =>representa los parámetros y la parte derecha expresa la operación que se ejecuta.
ASINCRONÍA
async y await: idea básica
Muchas operaciones modernas, como acceder a una API o trabajar con entrada/salida, pueden ejecutarse de forma asíncrona.
static async Task<string> ObtenerDatosAsync()
{ using var cliente=new HttpClient(); return await cliente.GetStringAsync("https://example.com");}awaitpermite esperar la finalización de una operación asíncrona sin tratarla como una espera bloqueante convencional.
La programación asíncrona requiere más conceptos que este ejemplo introductorio; aquí interesa reconocer su sintaxis y finalidad.
PRÁCTICA PROPUESTA
Ejercicio: catálogo de productos
Crea una pequeña aplicación que almacene productos con nombre, precio y stock.
El ejercicio debería permitir:
- Crear una clase
Producto. - Crear una lista de productos.
- Mostrar todos los productos.
- Filtrar los productos con stock disponible.
- Ordenarlos por precio.
- Calcular el valor total del stock.
Una posible base:
public class Producto
{
public string Nombre { get; set; } = "";
public decimal Precio { get; set; }
public int Stock { get; set; }
}
var productos = new List<Producto>
{
new() { Nombre = "Teclado", Precio = 45.90m, Stock = 8 },
new() { Nombre = "Ratón", Precio = 22.50m, Stock = 0 },
new() { Nombre = "Monitor", Precio = 189.00m, Stock = 4 }
};
var disponibles = productos
.Where(p => p.Stock > 0)
.OrderBy(p => p.Precio);
foreach (var producto in disponibles)
{
Console.WriteLine($"{producto.Nombre} - {producto.Precio:C}");
}Para completar el ejercicio, calcula también el valor total del inventario:
decimal valorInventario = productos
.Sum(p => p.Precio * p.Stock);
Console.WriteLine($"Valor del inventario: {valorInventario:C}");Este ejercicio permite combinar clases, colecciones, propiedades, LINQ y salida formateada.
ERRORES HABITUALES
Problemas frecuentes al empezar con C#
| Situación | Qué revisar |
|---|---|
| Error de conversión | Comprueba que el valor pueda convertirse al tipo esperado. |
NullReferenceException | Verifica que la referencia no sea nullantes de utilizarla. |
| Índice fuera de rango | Comprueba los límites del array o colección. |
| Secuencia vacía | Revisa operaciones como First()cuando la colección puede no contener elementos. |
| Comparación incorrecta | Distingue asignación, igualdad y condiciones lógicas. |
| Propiedad sin inicializar | Revisa constructores, inicializadores y nulabilidad. |
| Resultado inesperado con enteros | Comprueba los tipos involucrados en divisiones y otras operaciones numéricas. |
CRITERIO PROFESIONAL
Buenas prácticas básicas
- Utiliza nombres claros para clases, métodos, variables y propiedades.
- Evita clases y métodos con demasiadas responsabilidades.
- Utiliza tipos que representen correctamente los datos.
- Gestiona la nulabilidad de forma explícita.
- Captura excepciones concretas cuando realmente puedas tratarlas.
- Utiliza LINQ cuando mejore la legibilidad, no únicamente para escribir menos código.
- Evita duplicar lógica que pueda extraerse a un método o componente reutilizable.
- No almacenes claves, contraseñas ni secretos directamente en el código.
- Separa la lógica de negocio de presentación e infraestructura cuando la aplicación crezca.
- Escribe código pensando también en quien tendrá que mantenerlo después.
Una aplicación mantenible no depende únicamente de que el código funcione: también necesita ser comprensible, comprobable y fácil de modificar.
REFERENCIA RÁPIDA
Sintaxis esencial
| Acción | Ejemplo |
|---|---|
| Variable | int edad=30; |
| Inferencia | var nombre="Ana"; |
| Condicional | if (edad >=18){ ...} |
| Bucle | foreach (var x in lista){ ...} |
| Método | int Sumar(int a, int b) |
| Lista | new List<string>() |
| Diccionario | new Dictionary<string, int>() |
| Objeto | new Producto() |
| LINQ | lista.Where(x=> x.Activo) |
| Lambda | x=> x * 2 |
| Nulabilidad | string? nombre=null; |
| Coalescencia nula | valor ?? alternativa |
| Asíncrono | await MetodoAsync() |
PARA AMPLIAR
Documentación oficial
Esta guía está pensada como recurso de consulta y apoyo al aprendizaje. Para profundizar en las características del lenguaje y en las APIs del ecosistema .NET, conviene consultar la documentación oficial de Microsoft.