Descripción del curso C# OOP
La programación orientada a objetos (OOP) representa uno de los paradigmas más importantes en el desarrollo de software moderno. C# se ha consolidado como un lenguaje versátil y potente que implementa este paradigma de forma elegante y completa, convirtiéndose en una herramienta fundamental para desarrolladores profesionales en el ecosistema Microsoft y más allá.
¿Qué es la programación orientada a objetos?
La OOP es un paradigma de programación que utiliza "objetos" como elementos fundamentales. Estos objetos son instancias de clases, que funcionan como plantillas o moldes que definen las características (propiedades) y comportamientos (métodos) que tendrán los objetos creados a partir de ellas.
Este enfoque permite modelar problemas del mundo real de manera más intuitiva, organizando el código en unidades cohesivas que encapsulan datos y funcionalidad relacionada, facilitando así el desarrollo, mantenimiento y escalabilidad de aplicaciones complejas.
C# como lenguaje orientado a objetos
C# fue diseñado desde sus inicios como un lenguaje orientado a objetos puro, incorporando todos los conceptos fundamentales de este paradigma:
- Encapsulación: Permite ocultar los detalles internos de implementación y exponer solo lo necesario.
- Herencia: Facilita la reutilización de código mediante la creación de jerarquías de clases.
- Polimorfismo: Permite que objetos de diferentes clases respondan de manera distinta al mismo mensaje.
- Abstracción: Posibilita representar conceptos complejos de forma simplificada.
A lo largo de este curso, exploraremos estos conceptos y muchos más, desde los fundamentos hasta técnicas avanzadas que te permitirán aprovechar todo el potencial de C# como lenguaje OOP.
Fundamentos de clases y objetos en C#
En C#, todo comienza con las clases y objetos. Una clase es una estructura que define un tipo de datos, mientras que un objeto es una instancia concreta de esa clase. Por ejemplo:
// Definición de una clase
public class Persona
{
// Propiedades
public string Nombre { get; set; }
public int Edad { get; set; }
// Método
public void Presentarse()
{
Console.WriteLine($"Hola, soy {Nombre} y tengo {Edad} años.");
}
}
// Creación de un objeto (instancia de la clase)
Persona persona1 = new Persona();
persona1.Nombre = "Ana";
persona1.Edad = 30;
persona1.Presentarse(); // Salida: Hola, soy Ana y tengo 30 años.
Este ejemplo ilustra cómo una clase encapsula tanto datos (propiedades Nombre
y Edad
) como comportamiento (método Presentarse
).
Encapsulación y control de acceso
La encapsulación es un principio fundamental que permite controlar el acceso a los miembros de una clase. C# proporciona modificadores de acceso como public
, private
, protected
e internal
para este fin:
public class CuentaBancaria
{
// Campo privado - solo accesible dentro de la clase
private decimal _saldo;
// Propiedad pública con lógica de validación
public decimal Saldo
{
get { return _saldo; }
private set { _saldo = value; } // Solo se puede modificar dentro de la clase
}
public void Depositar(decimal cantidad)
{
if (cantidad <= 0)
throw new ArgumentException("La cantidad debe ser positiva");
_saldo += cantidad;
}
}
Este patrón de diseño protege los datos internos y garantiza que solo puedan modificarse a través de métodos controlados, manteniendo la integridad de los datos.
Constructores y ciclo de vida de los objetos
Los constructores son métodos especiales que se ejecutan cuando se crea un objeto, permitiendo inicializar sus propiedades. C# también proporciona destructores (o finalizadores) que se ejecutan cuando un objeto es eliminado por el recolector de basura:
public class Recurso
{
private string _nombre;
// Constructor sin parámetros
public Recurso()
{
_nombre = "Sin nombre";
Console.WriteLine("Recurso creado");
}
// Constructor con parámetros
public Recurso(string nombre)
{
_nombre = nombre;
Console.WriteLine($"Recurso '{_nombre}' creado");
}
// Destructor
~Recurso()
{
Console.WriteLine($"Recurso '{_nombre}' liberado");
}
}
C# también proporciona el patrón IDisposable
para una gestión más controlada de recursos:
public class ConexionBD : IDisposable
{
private bool _disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// Liberar recursos administrados
}
// Liberar recursos no administrados
_disposed = true;
}
}
}
Herencia y extensibilidad
La herencia permite crear nuevas clases basadas en clases existentes, heredando sus miembros y añadiendo o modificando funcionalidad:
// Clase base
public class Vehiculo
{
public string Marca { get; set; }
public string Modelo { get; set; }
public virtual void Arrancar()
{
Console.WriteLine("El vehículo está arrancando");
}
}
// Clase derivada
public class Coche : Vehiculo
{
public int NumeroPuertas { get; set; }
// Sobrescribe el método de la clase base
public override void Arrancar()
{
Console.WriteLine("El coche está arrancando con llave");
}
}
La palabra clave virtual
permite que los métodos sean sobrescritos en clases derivadas, mientras que override
indica que estamos redefiniendo un método de la clase base.
Polimorfismo y flexibilidad
El polimorfismo es la capacidad de tratar objetos de diferentes clases a través de una interfaz común. Esto proporciona gran flexibilidad al código:
public void ProcesarVehiculos(List<Vehiculo> vehiculos)
{
foreach (var vehiculo in vehiculos)
{
// Cada tipo de vehículo responderá según su implementación
vehiculo.Arrancar();
}
}
// Uso
var listaVehiculos = new List<Vehiculo>
{
new Coche { Marca = "Toyota", Modelo = "Corolla" },
new Motocicleta { Marca = "Honda", Modelo = "CBR" }
};
ProcesarVehiculos(listaVehiculos);
Interfaces y contratos
Las interfaces definen contratos que las clases pueden implementar, estableciendo qué métodos y propiedades deben proporcionar sin especificar cómo deben implementarse:
public interface IVolador
{
void Despegar();
void Aterrizar();
double CalcularAutonomia();
}
public class Avion : IVolador
{
public void Despegar()
{
Console.WriteLine("El avión está despegando");
}
public void Aterrizar()
{
Console.WriteLine("El avión está aterrizando");
}
public double CalcularAutonomia()
{
return 5000.0; // km
}
}
Las interfaces permiten implementar múltiples herencias de comportamiento, algo que no es posible con la herencia de clases en C#.
Clases abstractas
Las clases abstractas combinan características de las interfaces y las clases normales, permitiendo implementación parcial y definición de contratos:
public abstract class Animal
{
public string Nombre { get; set; }
// Método con implementación
public void Respirar()
{
Console.WriteLine("El animal está respirando");
}
// Método abstracto (sin implementación)
public abstract void HacerSonido();
}
public class Perro : Animal
{
// Obligatorio implementar los métodos abstractos
public override void HacerSonido()
{
Console.WriteLine("¡Guau!");
}
}
Genéricos para código reutilizable
Los genéricos permiten crear clases, interfaces y métodos que operan con tipos que se especifican cuando se crea una instancia o se invoca el método:
public class Contenedor<T>
{
private T _contenido;
public void Guardar(T item)
{
_contenido = item;
}
public T Obtener()
{
return _contenido;
}
}
// Uso con diferentes tipos
var contenedorEnteros = new Contenedor<int>();
contenedorEnteros.Guardar(42);
var contenedorCadenas = new Contenedor<string>();
contenedorCadenas.Guardar("Hola mundo");
Esta característica proporciona seguridad de tipos y evita conversiones innecesarias, mejorando el rendimiento y la legibilidad del código.
Delegados y eventos
Los delegados son tipos que representan referencias a métodos, permitiendo pasar métodos como parámetros:
// Definición de un delegado
public delegate int Operacion(int a, int b);
// Métodos que coinciden con la firma del delegado
public int Sumar(int a, int b) => a + b;
public int Multiplicar(int a, int b) => a * b;
// Uso del delegado
public void Calcular(int x, int y, Operacion operacion)
{
int resultado = operacion(x, y);
Console.WriteLine($"El resultado es: {resultado}");
}
// Llamadas
Calcular(5, 3, Sumar); // El resultado es: 8
Calcular(5, 3, Multiplicar); // El resultado es: 15
Los eventos son un mecanismo basado en delegados que permite a una clase notificar a otras cuando ocurre algo relevante:
public class Temporizador
{
// Definición del delegado para el evento
public delegate void TiempoTranscurridoHandler(object sender, EventArgs e);
// Declaración del evento
public event TiempoTranscurridoHandler TiempoTranscurrido;
public void Iniciar()
{
// Simulación de tiempo transcurrido
Thread.Sleep(1000);
// Disparar el evento
OnTiempoTranscurrido();
}
protected virtual void OnTiempoTranscurrido()
{
// Verificar si hay suscriptores antes de invocar
TiempoTranscurrido?.Invoke(this, EventArgs.Empty);
}
}
Características avanzadas
C# también ofrece características avanzadas como:
- Métodos de extensión: Permiten añadir métodos a tipos existentes sin modificarlos:
public static class StringExtensions
{
public static bool EsPalindromo(this string texto)
{
string textoNormalizado = texto.ToLower().Replace(" ", "");
char[] caracteres = textoNormalizado.ToCharArray();
Array.Reverse(caracteres);
string textoInvertido = new string(caracteres);
return textoNormalizado == textoInvertido;
}
}
// Uso
bool esPalindromo = "Anita lava la tina".EsPalindromo(); // true
- Tuplas y tipos anónimos: Facilitan el trabajo con datos estructurados sin necesidad de definir clases específicas:
// Tupla
(string Nombre, int Edad) persona = ("Carlos", 28);
Console.WriteLine($"{persona.Nombre} tiene {persona.Edad} años");
// Tipo anónimo
var producto = new { Id = 1, Nombre = "Laptop", Precio = 1200.50m };
Console.WriteLine($"Producto: {producto.Nombre}, Precio: {producto.Precio}€");
- Manejo de excepciones: Permite gestionar errores de forma estructurada:
try
{
int resultado = 10 / 0; // Esto generará una excepción
}
catch (DivideByZeroException ex)
{
Console.WriteLine($"Error matemático: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"Error general: {ex.Message}");
}
finally
{
Console.WriteLine("Este bloque siempre se ejecuta");
}
Aplicaciones prácticas
La programación orientada a objetos en C# se utiliza en una amplia variedad de aplicaciones:
- Desarrollo de aplicaciones empresariales con .NET y ASP.NET
- Desarrollo de videojuegos con Unity
- Aplicaciones de escritorio con WPF o Windows Forms
- Aplicaciones móviles con Xamarin o MAUI
- Servicios web y microservicios con ASP.NET Core
A lo largo de este curso, aprenderás a aplicar estos conceptos en situaciones reales, desarrollando habilidades prácticas que podrás utilizar en proyectos profesionales.
Buenas prácticas en OOP con C#
Para aprovechar al máximo la programación orientada a objetos en C#, es importante seguir algunas buenas prácticas:
- Principio de responsabilidad única: Cada clase debe tener una única razón para cambiar.
- Principio abierto/cerrado: Las entidades deben estar abiertas para extensión pero cerradas para modificación.
- Principio de sustitución de Liskov: Los objetos de una clase derivada deben poder sustituir a los objetos de la clase base sin afectar la corrección del programa.
- Principio de segregación de interfaces: Es mejor tener muchas interfaces específicas que una interfaz general.
- Principio de inversión de dependencias: Depender de abstracciones, no de implementaciones concretas.
Estos principios, conocidos como principios SOLID, te ayudarán a crear código más mantenible, extensible y robusto.
Herramientas y entorno de desarrollo
Para desarrollar aplicaciones con C# y OOP, utilizaremos:
- Visual Studio o Visual Studio Code: Entornos de desarrollo integrados (IDE) con potentes características para C#.
- .NET SDK: El kit de desarrollo de software que proporciona las herramientas necesarias para compilar y ejecutar aplicaciones .NET.
- NuGet: El gestor de paquetes para .NET que facilita la incorporación de bibliotecas externas.
Estas herramientas te proporcionarán un entorno completo para aplicar todos los conceptos que aprenderás en este curso.
A través de este itinerario, adquirirás una comprensión profunda de la programación orientada a objetos en C#, desde los conceptos fundamentales hasta técnicas avanzadas, preparándote para desarrollar aplicaciones robustas y mantenibles en el mundo profesional.
Lecciones de este curso
Explora todas las lecciones incluidas en este curso de programación
Explorar más cursos de programación
Descubre más cursos y hojas de ruta de programación

Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, se dedica a crear hojas de ruta y cursos de programación estructurados. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan diseña contenido educativo de calidad para desarrolladores de todos los niveles.