En C#, las clases y las estructuras actúan como plantillas para la creación de objetos. Las clases son tipos de referencia almacenados en el montón administrado, mientras que las estructuras son tipos de valor almacenados en la pila. Se utilizan las palabras clave class y struct respectivamente, y las instancias de clases se generan mediante new.
class ClienteTelefono
{
public const string DiaFacturacion = "Lunes";
public int IdCliente;
public void ObtenerDatos() { }
}
struct ClienteTelefonoEstructura
{
public const string DiaFacturacion = "Lunes";
}
var cliente = new ClienteTelefono();
cliente.ObtenerDatos();
Los miembros de datos en clases incluyen campos, constantes y eventos. Los modificadores de acceso controlan la visibilidad: public (acceso abierto), protected (accesible por clases derivadas), internal protected (accesible por clases derivadas dentro del mismo espacio de nombres), private (accesible solo dentro de la clase) e internal (accesible dentro del mismo espacio de nombres). Los miembros estáticos se declaran con static y las constantes con const.
Los miembros de función abarcan métodos, propiedades, constructores, entre otros. Un método se define con un modificador de acceso, tipo de retorno, nombre, lista de parámetros y cuerpo. La lista de parámetros especifica tipos y nombres, y se usa return para devolver valores, o void si no hay retorno.
public string ObtenerNombre(string nombre)
{
return "Mi nombre es: " + nombre;
}
public void MostrarNombre(string nombre)
{
Console.Write("Mi nombre es: " + nombre);
}
Los métodos se invocan a través de instancias de objetos, excepto los métodos estáticos que se llaman con el nombre de la clase. Los parámetros pueden pasarse por valor o por referencia; pasar por referencia permite modificaciones persistentes. Las palabras clave ref y out facilitan el paso por referencia, con out útil para múltiples valores de retorno. Los parámetros nombrados y opcionales mejoran la flexibilidad, con los opcionales requiirendo valores predeterminados.
public decimal CalcularTotal(int cantidad, decimal precioUnitario = 10)
{
return cantidad * precioUnitario;
}
// Llamadas: CalcularTotal(5) o CalcularTotal(5, 20)
La sobrecarga de métodos permite múltiples métodos con el mismo nombre pero diferentes parámetros en tipo o cantidad. Las propiedades encapsulan datos con accesores get y set, que pueden tener modificadores de acceso separados. Las propiedades automáticas simplifican la declaración sin definir accesores explícitos.
Los constructores inicializan instancias de clases, pueden sobrecargarse, y se usa this para llamar a otros constructores o base para constructroes de clases base. Los constructores estáticos se ejecutan una vez antes del primer uso de la clase y no pueden tener parámetros. Los campos de solo lectura se declaran con readonly y se asignan en tiempo de ejecución.
Los tipos anónimos se crean con var y new, son tipos sin nombre que heredan de Object. Sus propiedades son de solo lectura, a menos que contengan referencias a objetos modificables.
var capitan = new { Nombre = "Ana", Edad = 25 };
var doctor = new { Items = new List<int>(), Capitan = capitan };
Las estructuras son tipos de valor que no se pueden heredar y tienen constructores predeterminados. A diferencia de las clases, no requieren new para instanciarse, pero deben inicializarse antes de usar sus propiedades. Pasar estructuras como parámetros implica copiarlas, por lo que se recomienda ref para modificaciones.
Las referencias débiles, mediante la clase WeakReference, permiten que objetos grandes puedan ser recolectados por el recolector de basura cuando no hay referencias fuertes. Se verifica su existencia con IsAlive y se accede con Target, requiriendo conversión de tipo.
Las clases parciales, usando partial, dividen definniciones en múltiples archivos, manteniendo coherencia en atributos y modificadores. Las clases estáticas, marcadas con static, solo contienen miembros estáticos y se acceden directamente por su nombre.
La clase Object es la base de todos los tipos en .NET. Sus métodos clave incluyen ToString para representaciones de cadena, GetHashCode para estructuras de datos hash, Equals para comparación, Finalize para limpieza de recursos, GetType para información de tipo y MemberwiseClone para copias superficiales.
Los métodos de extensión se definen en clases estáticas y añaden funcionalidad a tipos existentes sin modificación. El primer parámetro usa this para indicar el tipo extendido, y se pueden llamar como métodos de instancia.