Tipos (Guía de programación de C#)Types (C# Programming Guide)

Tipos, variables y valoresTypes, Variables, and Values

C# es un lenguaje fuertemente tipado.C# is a strongly-typed language. Todas las variables y constantes tienen un tipo, al igual que todas las expresiones que se evalúan como un valor.Every variable and constant has a type, as does every expression that evaluates to a value. Cada una de las firmas de método especifica un tipo para cada parámetro de entrada y para el valor devuelto.Every method signature specifies a type for each input parameter and for the return value. La biblioteca de clases .NET define un conjunto de tipos numéricos integrados, así como tipos más complejos que representan una amplia variedad de construcciones lógicas, como el sistema de archivos, conexiones de red, colecciones y matrices de objetos, y fechas.The .NET class library defines a set of built-in numeric types as well as more complex types that represent a wide variety of logical constructs, such as the file system, network connections, collections and arrays of objects, and dates. Los programas de C# típicos usan tipos de la biblioteca de clases, así como tipos definidos por el usuario que modelan los conceptos que son específicos del dominio del problema del programa.A typical C# program uses types from the class library as well as user-defined types that model the concepts that are specific to the program's problem domain.

Entre la información almacenada en un tipo se puede incluir lo siguiente:The information stored in a type can include the following:

  • El espacio de almacenamiento que requiere una variable del tipo.The storage space that a variable of the type requires.

  • Los valores máximo y mínimo que puede representar.The maximum and minimum values that it can represent.

  • Los miembros (métodos, campos, eventos, etc.) que contiene.The members (methods, fields, events, and so on) that it contains.

  • El tipo base del que hereda.The base type it inherits from.

  • La ubicación donde se asignará la memoria para variables en tiempo de ejecución.The location where the memory for variables will be allocated at run time.

  • Los tipos de operaciones permitidas.The kinds of operations that are permitted.

El compilador usa información de tipo para garantizar que todas las operaciones que se realizan en el código cuentan con seguridad de tipos.The compiler uses type information to make sure that all operations that are performed in your code are type safe. Por ejemplo, si declara una variable de tipo int, el compilador le permite usar la variable en operaciones de suma y resta.For example, if you declare a variable of type int, the compiler allows you to use the variable in addition and subtraction operations. Si intenta realizar esas mismas operaciones en una variable de tipo bool, el compilador genera un error, como se muestra en el siguiente ejemplo:If you try to perform those same operations on a variable of type bool, the compiler generates an error, as shown in the following example:

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

Los desarrolladores de C y C++ deben tener en cuenta que, en C#, bool no se puede convertir en int.C and C++ developers, notice that in C#, bool is not convertible to int.

El compilador inserta la información de tipo en el archivo ejecutable como metadatos.The compiler embeds the type information into the executable file as metadata. Common Language Runtime (CLR) utiliza esos metadatos en tiempo de ejecución para garantizar aún más la seguridad de tipos cuando asigna y reclama memoria.The common language runtime (CLR) uses that metadata at run time to further guarantee type safety when it allocates and reclaims memory.

Definición de tipos en declaraciones de variableSpecifying Types in Variable Declarations

Cuando declare una variable o constante en un programa, debe especificar su tipo o utilizar la palabra clave var para que el compilador infiera el tipo.When you declare a variable or constant in a program, you must either specify its type or use the var keyword to let the compiler infer the type. En el ejemplo siguiente se muestran algunas declaraciones de variable que utilizan tanto tipos numéricos integrados como tipos complejos definidos por el usuario:The following example shows some variable declarations that use both built-in numeric types and complex user-defined types:

// Declaration only:
float temperature;
string name;
MyClass myClass;

// Declaration with initializers (four examples):
char firstLetter = 'C';
var limit = 3;
int[] source = { 0, 1, 2, 3, 4, 5 };
var query = from item in source
            where item <= limit
            select item;

Los tipos de parámetros de método y valores devueltos se especifican en la firma del método.The types of method parameters and return values are specified in the method signature. En la siguiente firma se muestra un método que requiere una variable int como argumento de entrada y devuelve una cadena:The following signature shows a method that requires an int as an input argument and returns a string:

public string GetName(int ID)
{
    if (ID < names.Length)
        return names[ID];
    else
        return String.Empty;
}
private string[] names = { "Spencer", "Sally", "Doug" };

Tras declarar una variable, no se puede volver a declarar con un nuevo tipo y no se le puede asignar un valor que no sea compatible con su tipo declarado.After a variable is declared, it cannot be re-declared with a new type, and it cannot be assigned a value that is not compatible with its declared type. Por ejemplo, no puede declarar un valor int y, luego, asignarle un valor booleano de true.For example, you cannot declare an int and then assign it a Boolean value of true. En cambio, los valores se pueden convertir en otros tipos, por ejemplo, cuando se asignan a variables nuevas o se pasan como argumentos de método.However, values can be converted to other types, for example when they are assigned to new variables or passed as method arguments. El compilador realiza automáticamente una conversión de tipo que no da lugar a una pérdida de datos.A type conversion that does not cause data loss is performed automatically by the compiler. Una conversión que pueda dar lugar a la pérdida de datos requiere un valor cast en el código fuente.A conversion that might cause data loss requires a cast in the source code.

Para obtener más información, vea Conversiones de tipos.For more information, see Casting and Type Conversions.

Tipos integradosBuilt-in Types

C# proporciona un conjunto estándar de tipos numéricos integrados para representar números enteros, valores de punto flotante, expresiones booleanas, caracteres de texto, valores decimales y otros tipos de datos.C# provides a standard set of built-in numeric types to represent integers, floating point values, Boolean expressions, text characters, decimal values, and other types of data. También hay tipos string y object integrados.There are also built-in string and object types. Están disponibles para su uso en cualquier programa de C#.These are available for you to use in any C# program. Para obtener más información sobre los tipos integrados, vea Tablas de referencia para tipo integrados.For more information about the built-in types, see Reference Tables for built-in Types.

Tipos personalizadosCustom Types

Las construcciones struct, class, interface y enum se utilizan para crear sus propios tipos personalizados.You use the struct, class, interface, and enum constructs to create your own custom types. La biblioteca de clases .NET es en sí misma una colección de tipos personalizados proporcionados por Microsoft que puede usar en sus propias aplicaciones.The .NET class library itself is a collection of custom types provided by Microsoft that you can use in your own applications. De forma predeterminada, los tipos usados con más frecuencia en la biblioteca de clases están disponibles en cualquier programa de C#.By default, the most frequently used types in the class library are available in any C# program. Otros están disponibles solo cuando agrega explícitamente una referencia de proyecto al ensamblado en el que se definen.Others become available only when you explicitly add a project reference to the assembly in which they are defined. Una vez que el compilador tenga una referencia al ensamblado, puede declarar variables (y constantes) de los tipos declarados en dicho ensamblado en el código fuente.After the compiler has a reference to the assembly, you can declare variables (and constants) of the types declared in that assembly in source code. Para más información, vea Biblioteca de clases .NET.For more information, see .NET Class Library.

Common Type SystemThe Common Type System

Es importante entender dos aspectos fundamentales sobre el sistema de tipos en .NET:It is important to understand two fundamental points about the type system in .NET:

  • Es compatible con el principio de herencia.It supports the principle of inheritance. Los tipos pueden derivarse de otros tipos, denominados tipos base.Types can derive from other types, called base types. El tipo derivado hereda (con algunas restricciones), los métodos, las propiedades y otros miembros del tipo base.The derived type inherits (with some restrictions) the methods, properties, and other members of the base type. A su vez, el tipo base puede derivarse de algún otro tipo, en cuyo caso el tipo derivado hereda los miembros de ambos tipos base en su jerarquía de herencia.The base type can in turn derive from some other type, in which case the derived type inherits the members of both base types in its inheritance hierarchy. Todos los tipos, incluidos los tipos numéricos integrados como System.Int32 (palabra clave de C#: int), derivan en última instancia de un único tipo base, que es System.Object (palabra clave de C#: object).All types, including built-in numeric types such as System.Int32 (C# keyword: int), derive ultimately from a single base type, which is System.Object (C# keyword: object). Esta jerarquía de tipos unificada se denomina Common Type System (CTS).This unified type hierarchy is called the Common Type System (CTS). Para más información sobre la herencia en C#, vea Herencia.For more information about inheritance in C#, see Inheritance.

  • En CTS, cada tipo se define como un tipo de valor o un tipo de referencia.Each type in the CTS is defined as either a value type or a reference type. Esto incluye todos los tipos personalizados de la biblioteca de clases .NET y también sus propios tipos definidos por el usuario.This includes all custom types in the .NET class library and also your own user-defined types. Los tipos que se definen mediante el uso de la palabra clave struct son tipos de valor; todos los tipos numéricos integrados son structs.Types that you define by using the struct keyword are value types; all the built-in numeric types are structs. Los tipos que se definen mediante el uso de la palabra clave class son tipos de referencia.Types that you define by using the class keyword are reference types. Los tipos de referencia y los tipos de valor tienen distintas reglas de tiempo de compilación y distintos comportamientos de tiempo de ejecución.Reference types and value types have different compile-time rules, and different run-time behavior.

En la ilustración siguiente se muestra la relación entre los tipos de valor y los tipos de referencia en CTS.The following illustration shows the relationship between value types and reference types in the CTS.

En la imagen siguiente se muestran tipos de valores y tipos de referencias en CTS:The following image shows value types and reference types in the CTS:

Captura de pantalla en la que se muestran tipos de valores y tipos de referencias en CTS.

Nota

Puede ver que los tipos utilizados con mayor frecuencia están organizados en el espacio de nombres System.You can see that the most commonly used types are all organized in the System namespace. Sin embargo, el espacio de nombres que contiene un tipo no tiene ninguna relación con un tipo de valor o un tipo de referencia.However, the namespace in which a type is contained has no relation to whether it is a value type or reference type.

Tipos de valorValue Types

Los tipos de valor derivan de System.ValueType, el cual deriva de System.Object.Value types derive from System.ValueType, which derives from System.Object. Los tipos que derivan de System.ValueType tienen un comportamiento especial en CLR.Types that derive from System.ValueType have special behavior in the CLR. Las variables de tipo de valor contienen directamente sus valores, lo que significa que la memoria se asigna insertada en cualquier contexto en el que se declare la variable.Value type variables directly contain their values, which means that the memory is allocated inline in whatever context the variable is declared. No se produce ninguna asignación del montón independiente ni sobrecarga de la recolección de elementos no utilizados para las variables de tipo de valor.There is no separate heap allocation or garbage collection overhead for value-type variables.

Existen dos categorías de tipos de valor: struct y enum.There are two categories of value types: struct and enum.

Los tipos numéricos integrados son structs y tienen propiedades y métodos a los que se puede obtener acceso:The built-in numeric types are structs, and they have properties and methods that you can access:

// Static method on type byte.
byte b = byte.MaxValue;

Pero se declaran y se les asignan valores como si fueran tipos simples no agregados:But you declare and assign values to them as if they were simple non-aggregate types:

byte num = 0xA;
int i = 5;
char c = 'Z';

Los tipos de valor están sellados, lo que significa que, por ejemplo, no puede derivar un tipo de System.Int32, y no puede definir un struct para que herede de cualquier clase o struct definido por el usuario, porque un struct solo puede heredar de System.ValueType.Value types are sealed, which means, for example, that you cannot derive a type from System.Int32, and you cannot define a struct to inherit from any user-defined class or struct because a struct can only inherit from System.ValueType. A pesar de ello, un struct puede implementar una o más interfaces.However, a struct can implement one or more interfaces. Puede convertir un tipo struct en cualquier tipo de interfaz que implemente. Esto hace que una operación de conversión boxing encapsule el struct dentro de un objeto de tipo de referencia en el montón administrado.You can cast a struct type to any interface type that it implements; this causes a boxing operation to wrap the struct inside a reference type object on the managed heap. Las operaciones de conversión boxing se producen cuando se pasa un tipo de valor a un método que toma System.Object o cualquier tipo de interfaz como parámetro de entrada.Boxing operations occur when you pass a value type to a method that takes a System.Object or any interface type as an input parameter. Para obtener más información, vea Conversión boxing y unboxing.For more information, see Boxing and Unboxing.

Puede usar la palabra clave struct para crear sus propios tipos de valor personalizados.You use the struct keyword to create your own custom value types. Normalmente, un struct se usa como un contenedor para un pequeño conjunto de variables relacionadas, como se muestra en el ejemplo siguiente:Typically, a struct is used as a container for a small set of related variables, as shown in the following example:

public struct Coords
{
    public int x, y;

    public Coords(int p1, int p2)
    {
        x = p1;
        y = p2;
    }
}

Para más información sobre estructuras, vea Structs.For more information about structs, see Structs. Para más información sobre los tipos de valor en. NET, vea Tipos de valor.For more information about value types in .NET, see Value Types.

La otra categoría de tipos de valor es enum.The other category of value types is enum. Una enumeración define un conjunto de constantes integrales con nombre.An enum defines a set of named integral constants. Por ejemplo, la enumeración System.IO.FileMode de la biblioteca de clases .NET contiene un conjunto de enteros constantes con nombre que especifican cómo se debe abrir un archivo.For example, the System.IO.FileMode enumeration in the .NET class library contains a set of named constant integers that specify how a file should be opened. Se define como se muestra en el ejemplo siguiente:It is defined as shown in the following example:

public enum FileMode
{
    CreateNew = 1,
    Create = 2,
    Open = 3,
    OpenOrCreate = 4,
    Truncate = 5,
    Append = 6,
}

La constante System.IO.FileMode.Create tiene un valor de 2.The System.IO.FileMode.Create constant has a value of 2. Sin embargo, el nombre es mucho más significativo para los humanos que leen el código fuente y, por esa razón, es mejor utilizar enumeraciones en lugar de números literales constantes.However, the name is much more meaningful for humans reading the source code, and for that reason it is better to use enumerations instead of constant literal numbers. Para más información, consulte System.IO.FileMode.For more information, see System.IO.FileMode.

Todas las enumeraciones se heredan de System.Enum, el cual se hereda de System.ValueType.All enums inherit from System.Enum, which inherits from System.ValueType. Todas las reglas que se aplican a las estructuras también se aplican a las enumeraciones.All the rules that apply to structs also apply to enums. Para más información sobre las enumeraciones, vea Tipos de enumeración.For more information about enums, see Enumeration Types.

Tipos de referenciaReference Types

Un tipo que se define como clase, delegado, matriz o interfaz es un tipo de referencia.A type that is defined as a class, delegate, array, or interface is a reference type. Al declarar una variable de un tipo de referencia en tiempo de ejecución, esta contendrá el valor null hasta que se cree explícitamente un objeto mediante el operador new, o bien que se le asigne un objeto creado en otro lugar mediante new, tal y como se muestra en el ejemplo siguiente:At run time, when you declare a variable of a reference type, the variable contains the value null until you explicitly create an object by using the new operator, or assign it an object that has been created elsewhere by using new, as shown in the following example:

MyClass mc = new MyClass();
MyClass mc2 = mc;

Una interfaz debe inicializarse junto con un objeto de clase que lo implementa.An interface must be initialized together with a class object that implements it. Si MyClass implementa IMyInterface, cree una instancia de IMyInterface, tal como se muestra en el ejemplo siguiente:If MyClass implements IMyInterface, you create an instance of IMyInterface as shown in the following example:

IMyInterface iface = new MyClass();

Cuando se crea el objeto, se asigna la memoria en el montón administrado y la variable solo contiene una referencia a la ubicación del objeto.When the object is created, the memory is allocated on the managed heap, and the variable holds only a reference to the location of the object. Los tipos del montón administrado producen sobrecarga cuando se asignan y cuando los reclama la función de administración de memoria automática de CLR, conocida como recolección de elementos no utilizados.Types on the managed heap require overhead both when they are allocated and when they are reclaimed by the automatic memory management functionality of the CLR, which is known as garbage collection. En cambio, la recolección de elementos no utilizados también está muy optimizada y no crea problemas de rendimiento en la mayoría de los escenarios.However, garbage collection is also highly optimized, and in most scenarios it does not create a performance issue. Para obtener más información sobre la recolección de elementos no utilizados, vea Administración de memoria automática.For more information about garbage collection, see Automatic Memory Management.

Todas las matrices son tipos de referencia, incluso si sus elementos son tipos de valor.All arrays are reference types, even if their elements are value types. Las matrices derivan de manera implícita de la clase System.Array, pero el usuario las declara y las usa con la sintaxis simplificada que proporciona C#, como se muestra en el ejemplo siguiente:Arrays implicitly derive from the System.Array class, but you declare and use them with the simplified syntax that is provided by C#, as shown in the following example:

// Declare and initialize an array of integers.
int[] nums = { 1, 2, 3, 4, 5 };

// Access an instance property of System.Array.
int len = nums.Length;

Los tipos de referencia admiten la herencia completamente.Reference types fully support inheritance. Al crear una clase, puede heredar de cualquier otra interfaz o clase que no esté definida como sealed; y otras clases pueden heredar de la clase e invalidar sus métodos virtuales.When you create a class, you can inherit from any other interface or class that is not defined as sealed, and other classes can inherit from your class and override your virtual methods. Para más información sobre cómo crear clases propias, vea Clases y structs.For more information about how to create your own classes, see Classes and Structs. Para más información sobre la herencia y los métodos virtuales, vea Herencia.For more information about inheritance and virtual methods, see Inheritance.

Tipos de valores literalesTypes of Literal Values

En C#, los valores literales reciben un tipo del compilador.In C#, literal values receive a type from the compiler. Puede especificar cómo debe escribirse un literal numérico; para ello, anexe una letra al final del número.You can specify how a numeric literal should be typed by appending a letter to the end of the number. Por ejemplo, para especificar que el valor 4.56 debe tratarse como un valor flotante, anexe "f" o "F" después del número: 4.56f.For example, to specify that the value 4.56 should be treated as a float, append an "f" or "F" after the number: 4.56f. Si no se anexa ninguna letra, el compilador inferirá un tipo para el literal.If no letter is appended, the compiler will infer a type for the literal. Para obtener más información sobre los tipos que se pueden especificar con sufijos de letras, vea las páginas de referencia de los tipos individuales en Tipos de valor.For more information about which types can be specified with letter suffixes, see the reference pages for individual types in Value Types.

Dado que los literales tienen tipo y todos los tipos derivan en última instancia de System.Object, puede escribir y compilar código como el siguiente:Because literals are typed, and all types derive ultimately from System.Object, you can write and compile code such as the following:

string s = "The answer is " + 5.ToString();
// Outputs: "The answer is 5"
Console.WriteLine(s);

Type type = 12345.GetType();
// Outputs: "System.Int32"
Console.WriteLine(type);

Tipos genéricosGeneric Types

Los tipos se pueden declarar con uno o varios parámetros de tipo que actúan como un marcador de posición para el tipo real (el tipo concreto) que proporcionará el código de cliente cuando cree una instancia del tipo.A type can be declared with one or more type parameters that serve as a placeholder for the actual type (the concrete type) that client code will provide when it creates an instance of the type. Estos tipos se denominan tipos genéricos.Such types are called generic types. Por ejemplo, el tipo de .NET System.Collections.Generic.List<T> tiene un parámetro de tipo al que, por convención, se le denomina T. Cuando crea una instancia del tipo, especifica el tipo de los objetos que contendrá la lista, por ejemplo, la cadena:For example, the .NET type System.Collections.Generic.List<T> has one type parameter that by convention is given the name T. When you create an instance of the type, you specify the type of the objects that the list will contain, for example, string:

List<string> stringList = new List<string>();
stringList.Add("String example");
// compile time error adding a type other than a string:
stringList.Add(4);

El uso del parámetro de tipo permite reutilizar la misma clase para incluir cualquier tipo de elemento, sin necesidad de convertir cada elemento en object.The use of the type parameter makes it possible to reuse the same class to hold any type of element, without having to convert each element to object. Las clases de colección genéricas se denominan colecciones fuertemente tipadas porque el compilador conoce el tipo específico de los elementos de la colección y puede generar un error en tiempo de compilación si, por ejemplo, intenta agregar un valor entero al objeto stringList del ejemplo anterior.Generic collection classes are called strongly-typed collections because the compiler knows the specific type of the collection's elements and can raise an error at compile-time if, for example, you try to add an integer to the stringList object in the previous example. Para más información, vea Genéricos.For more information, see Generics.

Tipos implícitos, tipos anónimos y tipos que aceptan valores NULLImplicit Types, Anonymous Types, and Nullable Types

Como se ha mencionado anteriormente, puede asignar implícitamente un tipo a una variable local (pero no miembros de clase) mediante la palabra clave var.As stated previously, you can implicitly type a local variable (but not class members) by using the var keyword. La variable sigue recibiendo un tipo en tiempo de compilación, pero este lo proporciona el compilador.The variable still receives a type at compile time, but the type is provided by the compiler. Para más información, vea Variables locales con asignación implícita de tipos.For more information, see Implicitly Typed Local Variables.

En algunos casos, resulta conveniente crear un tipo con nombre para conjuntos sencillos de valores relacionados que no desea almacenar ni pasar fuera de los límites del método.In some cases, it is inconvenient to create a named type for simple sets of related values that you do not intend to store or pass outside method boundaries. Puede crear tipos anónimos para este fin.You can create anonymous types for this purpose. Para más información, vea Tipos anónimos.For more information, see Anonymous Types.

Los tipos de valor normales no pueden tener un valor null,Ordinary value types cannot have a value of null. pero se pueden crear tipos de valor que aceptan valores NULL mediante la adición de ? después del tipo.However, you can create nullable value types by affixing a ? after the type. Por ejemplo, int? es un tipo int que también puede tener el valor null.For example, int? is an int type that can also have the value null. En CTS, los tipos que aceptan valores NULL son instancias del tipo struct genérico System.Nullable<T>.In the CTS, nullable types are instances of the generic struct type System.Nullable<T>. Los tipos que aceptan valores NULL son especialmente útiles cuando se pasan datos hacia y desde bases de datos en las que los valores numéricos podrían ser nulos.Nullable types are especially useful when you are passing data to and from databases in which numeric values might be null. Para más información, vea Tipos que aceptan valores NULL.For more information, see Nullable Types.

Para obtener más información, vea los temas siguientes:For more information, see the following topics:

Especificación del lenguaje C#C# Language Specification

Para obtener más información, consulte la Especificación del lenguaje C#.For more information, see the C# Language Specification. La especificación del lenguaje es la fuente definitiva de la sintaxis y el uso de C#.The language specification is the definitive source for C# syntax and usage.

Vea tambiénSee also