Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Sugerencia
¿No está familiarizado con el desarrollo de software? Comience primero con los tutoriales de introducción . Te guiarán por la escritura de programas e introducen tipos a medida que avanzas.
¿Competente en otro idioma? Si ya entiende los sistemas de tipos, repase rápidamente la distinción entre valor y referencia y elija la guía sobre qué tipo elegir, luego pase a los artículos sobre tipos específicos.
C# es un lenguaje fuertemente tipado. Cada variable, constante y expresión tiene un tipo. El compilador aplica la seguridad de tipos comprobando que todas las operaciones del código son válidas para los tipos implicados. Por ejemplo, puede sumar dos int valores, pero no puede sumar un int y un bool.
int a = 5;
int b = a + 2; // OK
bool test = true;
// Error. Operator '+' cannot be applied to operands of type 'int' and 'bool'.
// int c = a + test;
Nota:
A diferencia de C y C++, en C#, bool no se puede convertir en int.
La seguridad de tipos detecta errores en el tiempo de compilación, antes de que se ejecute el código. El compilador también inserta información de tipo en el ejecutable como metadatos, que Common Language Runtime (CLR) usa para comprobaciones de seguridad adicionales en tiempo de ejecución.
Declarar variables con tipos
Al declarar una variable, especifique su tipo explícitamente o use var para permitir que el compilador infiera el tipo del valor asignado:
// Explicit type:
int count = 10;
double temperature = 36.6;
// Compiler-inferred type:
var name = "C#";
var items = new List<string> { "one", "two", "three" };
Los parámetros de método y los valores devueltos también tienen tipos. El método siguiente toma un string y un int, y devuelve un string:
static string GetGreeting(string name, int visitCount)
{
return visitCount switch
{
1 => $"Welcome, {name}!",
_ => $"Welcome back, {name}! Visit #{visitCount}."
};
}
Después de declarar una variable, no puede cambiar su tipo ni asignar un valor incompatible con el tipo declarado. Puede convertir valores a otros tipos. El compilador realiza conversiones implícitas que no pierden datos automáticamente. Las conversiones explícitas requieren que indique la conversión en su código. Para obtener más información, vea Casting y conversiones de tipo.
Tipos integrados y tipos personalizados
C# proporciona tipos integrados para datos comunes: enteros, números de punto flotante, bool, chary string. Cada programa de C# puede usar estos tipos integrados sin referencias adicionales.
Más allá de los tipos integrados, puede crear sus propios tipos mediante varias construcciones:
- Clases : tipos de referencia para el comportamiento de modelado y objetos complejos. Admite la herencia y el polimorfismo.
- Structs : tipos de valor para datos pequeños y ligeros. Cada variable contiene su propia copia.
-
Registros : clases o estructuras con igualdad generada por el compilador,
ToStringy mutación no destructiva a travéswithde expresiones. - Interfaces : contratos que definen miembros que cualquier clase o estructura pueden implementar.
- Enumeraciones : conjuntos con nombre de constantes integrales, como días de la semana o modos de acceso a archivos.
- Tuplas : tipos estructurales ligeros que agrupan valores relacionados sin definir un tipo con nombre.
-
Genéricos : construcciones con parámetros de tipo como
List<T>yDictionary<TKey, TValue>que proporcionan seguridad de tipos al reutilizar la misma lógica para distintos tipos.
Tipos de valor y tipos de referencia
Cada tipo de C# es un tipo de valor o un tipo de referencia. Esta distinción determina cómo las variables almacenan datos y cómo opera la asignación.
Los tipos de valor contienen sus datos directamente. Al asignar un tipo de valor a una nueva variable, el tiempo de ejecución copia los datos. Los cambios en una variable no afectan a la otra. Las estructuras, las enumeraciones y los tipos numéricos integrados son todos los tipos de valor.
Los tipos de referencia contienen una referencia a un objeto en el montón administrado. Al asignar un tipo de referencia a una nueva variable, ambas variables apuntan al mismo objeto. Los cambios a través de una variable son visibles a través de la otra. Las clases, matrices, delegados y cadenas son tipos de referencia.
En el ejemplo siguiente se muestra la diferencia. El primer bloque muestra la definición de la estructura de Coords registro, que es un tipo de valor. El segundo bloque muestra el comportamiento diferente para los tipos de valor y los tipos de referencia.
public readonly record struct Coords(int X, int Y);
// Value type: each variable holds its own copy
var point1 = new Coords(3, 4);
var point2 = point1;
Console.WriteLine($"point1: ({point1.X}, {point1.Y})");
Console.WriteLine($"point2: ({point2.X}, {point2.Y})");
// point1 and point2 are independent copies
// Reference type: both variables refer to the same object
var list1 = new List<int> { 1, 2, 3 };
var list2 = list1;
list2.Add(4);
Console.WriteLine($"list1 count: {list1.Count}"); // 4 — same object
En última instancia, todos los tipos derivan de System.Object. Los tipos de valor derivan de System.ValueType, que se deriva de object. Esta jerarquía unificada se denomina Common Type System (CTS). Para obtener más información sobre la herencia, vea Herencia.
Elegir el tipo de tipo
Al definir un nuevo tipo, el tipo que elige determina cómo se comporta el código. Use las instrucciones siguientes para tomar una decisión inicial:
- Tupla : agrupación temporal de valores que no necesitan un tipo o comportamiento con nombre.
-
structorecord struct— Datos pequeños (aproximadamente 64 bytes o menos), semántica de valores o inmutabilidad. Las estructuras de registro agregan igualdad basada en valores y expresioneswith. -
record class— Principalmente los datos, con igualdad basada en valores,ToStringy mutación no destructiva. Admite la herencia. -
class— Comportamiento complejo, polimorfismo o estado mutable. La mayoría de los tipos personalizados son clases. -
interface— Un contrato que pueden implementar tipos no relacionados. Define las funcionalidades en lugar de la identidad. -
enum— Un conjunto fijo de constantes con nombre, como códigos de estado o opciones.
Más de una opción suele ser razonable.
Tipo en tiempo de compilación y tipo en tiempo de ejecución
Una variable puede tener diferentes tipos en tiempo de compilación y tiempo de ejecución. El tipo de tiempo de compilación es el tipo declarado o inferido en el código fuente. El tipo en tiempo de ejecución es el tipo real de la instancia a la que hace referencia la variable. El tipo en tiempo de ejecución debe ser el mismo que el tipo en tiempo de compilación o un tipo que derive de él o lo implemente. Una asignación solo es válida cuando existe una conversión implícita desde el tipo en tiempo de ejecución al tipo en tiempo de compilación, como una conversión de identidad, de referencia, de tipo por caja (boxing), o numérica.
// Compile-time and run-time types match:
string message = "Hello, world!";
// Compile-time type differs from run-time type:
object boxed = "This is a string at run time";
IEnumerable<char> characters = "abcdefghijklmnopqrstuvwxyz";
En el ejemplo anterior, boxed tiene un tipo en tiempo de compilación de object , pero un tipo en tiempo de ejecución de string. La asignación funciona porque string se deriva de object. Del mismo modo, characters tiene un tipo en tiempo de compilación de IEnumerable<char>, y la asignación funciona porque string implementa esa interfaz. El tipo en tiempo de compilación controla la resolución de sobrecargas y las conversiones disponibles. El tipo en tiempo de ejecución controla el despacho de métodos virtuales, las is expresiones y las switch expresiones.
Consulte también
Especificación del lenguaje C#
Para obtener más información, consulte la Especificación del lenguaje C#. La especificación del lenguaje es el origen definitivo de la sintaxis y el uso de C#.