TiposTypes

Los tipos del lenguaje C# se dividen en dos categorías principales: tipos de valor _ y _tipos de referencia*.The types of the C# language are divided into two main categories: value types _ and _reference types*. Ambos tipos de valor y tipos de referencia pueden ser tipos genéricos, que toman uno o varios parámetros de tipo _ * * *.Both value types and reference types may be generic types, which take one or more _*type parameters**. Los parámetros de tipo pueden designar tanto tipos de valor como tipos de referencia.Type parameters can designate both value types and reference types.

type
    : value_type
    | reference_type
    | type_parameter
    | type_unsafe
    ;

La categoría final de tipos, punteros, solo está disponible en código no seguro.The final category of types, pointers, is available only in unsafe code. Esto se describe con más detalle en tipos de puntero.This is discussed further in Pointer types.

Los tipos de valor se diferencian de los tipos de referencia en que las variables de los tipos de valor contienen directamente sus datos, mientras que las variables de los tipos de referencia almacenan referencias en sus datos, lo que se conoce como "objetos *".Value types differ from reference types in that variables of the value types directly contain their data, whereas variables of the reference types store references _ to their data, the latter being known as _objects**. Con los tipos de referencia, es posible que dos variables hagan referencia al mismo objeto y, por lo tanto, las operaciones en una variable afecten al objeto al que hace referencia la otra variable.With reference types, it is possible for two variables to reference the same object, and thus possible for operations on one variable to affect the object referenced by the other variable. Con los tipos de valor, cada variable tiene su propia copia de los datos y no es posible que las operaciones en una afecten a la otra.With value types, the variables each have their own copy of the data, and it is not possible for operations on one to affect the other.

El sistema de tipos de C# está unificado, de modo que un valor de cualquier tipo se puede tratar como un objeto.C#'s type system is unified such that a value of any type can be treated as an object. Todos los tipos de C# directa o indirectamente se derivan del tipo de clase object, y object es la clase base definitiva de todos los tipos.Every type in C# directly or indirectly derives from the object class type, and object is the ultimate base class of all types. Los valores de tipos de referencia se tratan como objetos mediante la visualización de los valores como tipo object.Values of reference types are treated as objects simply by viewing the values as type object. Los valores de los tipos de valor se tratan como objetos realizando las operaciones de conversión boxing y unboxing (conversión boxing y conversión unboxing).Values of value types are treated as objects by performing boxing and unboxing operations (Boxing and unboxing).

Tipos de valorValue types

Un tipo de valor es un tipo de estructura o un tipo de enumeración.A value type is either a struct type or an enumeration type. C# proporciona un conjunto de tipos de struct predefinidos denominados tipos simples.C# provides a set of predefined struct types called the simple types. Los tipos simples se identifican mediante palabras reservadas.The simple types are identified through reserved words.

value_type
    : struct_type
    | enum_type
    ;

struct_type
    : type_name
    | simple_type
    | nullable_type
    ;

simple_type
    : numeric_type
    | 'bool'
    ;

numeric_type
    : integral_type
    | floating_point_type
    | 'decimal'
    ;

integral_type
    : 'sbyte'
    | 'byte'
    | 'short'
    | 'ushort'
    | 'int'
    | 'uint'
    | 'long'
    | 'ulong'
    | 'char'
    ;

floating_point_type
    : 'float'
    | 'double'
    ;

nullable_type
    : non_nullable_value_type '?'
    ;

non_nullable_value_type
    : type
    ;

enum_type
    : type_name
    ;

A diferencia de una variable de un tipo de referencia, una variable de un tipo de valor solo puede contener el valor null si el tipo de valor es un tipo que acepta valores NULL.Unlike a variable of a reference type, a variable of a value type can contain the value null only if the value type is a nullable type. Para cada tipo de valor que no acepta valores NULL, hay un tipo de valor que acepta valores NULL correspondiente que denota el mismo conjunto de valores más el valor null .For every non-nullable value type there is a corresponding nullable value type denoting the same set of values plus the value null.

La asignación a una variable de un tipo de valor crea una copia del valor que se va a asignar.Assignment to a variable of a value type creates a copy of the value being assigned. Esto difiere de la asignación a una variable de un tipo de referencia, que copia la referencia pero no el objeto identificado por la referencia.This differs from assignment to a variable of a reference type, which copies the reference but not the object identified by the reference.

Tipo System. ValueTypeThe System.ValueType type

Todos los tipos de valor heredan implícitamente de la clase System.ValueType , que, a su vez, hereda de la clase object .All value types implicitly inherit from the class System.ValueType, which, in turn, inherits from class object. No es posible que ningún tipo derive de un tipo de valor y, por tanto, los tipos de valor están sellados implícitamente (clases selladas).It is not possible for any type to derive from a value type, and value types are thus implicitly sealed (Sealed classes).

Tenga en cuenta que System.ValueType no es un value_type.Note that System.ValueType is not itself a value_type. En su lugar, es una class_type de la que se derivan automáticamente todos los value_type s.Rather, it is a class_type from which all value_type s are automatically derived.

Constructores predeterminadosDefault constructors

Todos los tipos de valor declaran implícitamente un constructor de instancia sin parámetros público denominado *constructor predeterminado _.All value types implicitly declare a public parameterless instance constructor called the *default constructor _. El constructor predeterminado devuelve una instancia inicializada en cero, conocida como el valor _ default* para el tipo de valor:The default constructor returns a zero-initialized instance known as the _ default value* for the value type:

  • Para todos los Simple_Type s, el valor predeterminado es el valor generado por un patrón de bits de todos los ceros:For all simple_type s, the default value is the value produced by a bit pattern of all zeros:
    • Para sbyte , byte , short , ushort , int , uint , long y ulong , el valor predeterminado es 0 .For sbyte, byte, short, ushort, int, uint, long, and ulong, the default value is 0.
    • En char , el valor predeterminado es '\x0000' .For char, the default value is '\x0000'.
    • En float , el valor predeterminado es 0.0f .For float, the default value is 0.0f.
    • En double , el valor predeterminado es 0.0d .For double, the default value is 0.0d.
    • En decimal , el valor predeterminado es 0.0m .For decimal, the default value is 0.0m.
    • En bool , el valor predeterminado es false .For bool, the default value is false.
  • Para un enum_type E , el valor predeterminado es 0 , convertido al tipo E .For an enum_type E, the default value is 0, converted to the type E.
  • Para un struct_type, el valor predeterminado es el valor generado al establecer todos los campos de tipo de valor en sus valores predeterminados y todos los campos de tipo de referencia en null .For a struct_type, the default value is the value produced by setting all value type fields to their default value and all reference type fields to null.
  • Para un nullable_type el valor predeterminado es una instancia para la que la HasValue propiedad es false y la Value propiedad no está definida.For a nullable_type the default value is an instance for which the HasValue property is false and the Value property is undefined. El valor predeterminado también se conoce como el valor null del tipo que acepta valores NULL.The default value is also known as the null value of the nullable type.

Al igual que cualquier otro constructor de instancia, el constructor predeterminado de un tipo de valor se invoca mediante el new operador.Like any other instance constructor, the default constructor of a value type is invoked using the new operator. Por motivos de eficacia, este requisito no está diseñado para tener realmente la implementación que genera una llamada al constructor.For efficiency reasons, this requirement is not intended to actually have the implementation generate a constructor call. En el ejemplo siguiente, las variables i y j se inicializan en cero.In the example below, variables i and j are both initialized to zero.

class A
{
    void F() {
        int i = 0;
        int j = new int();
    }
}

Dado que cada tipo de valor tiene implícitamente un constructor de instancia sin parámetros público, no es posible que un tipo de struct contenga una declaración explícita de un constructor sin parámetros.Because every value type implicitly has a public parameterless instance constructor, it is not possible for a struct type to contain an explicit declaration of a parameterless constructor. Sin embargo, se permite que un tipo de estructura declare constructores de instancia con parámetros (constructores).A struct type is however permitted to declare parameterized instance constructors (Constructors).

Tipos de estructuraStruct types

Un tipo de estructura es un tipo de valor que puede declarar constantes, campos, métodos, propiedades, indizadores, operadores, constructores de instancias, constructores estáticos y tipos anidados.A struct type is a value type that can declare constants, fields, methods, properties, indexers, operators, instance constructors, static constructors, and nested types. La declaración de tipos de struct se describe en declaraciones de struct.The declaration of struct types is described in Struct declarations.

Tipos simplesSimple types

C# proporciona un conjunto de tipos de struct predefinidos denominados tipos simples.C# provides a set of predefined struct types called the simple types. Los tipos simples se identifican mediante palabras reservadas, pero estas palabras reservadas son simplemente alias para los tipos de struct predefinidos en el System espacio de nombres, tal como se describe en la tabla siguiente.The simple types are identified through reserved words, but these reserved words are simply aliases for predefined struct types in the System namespace, as described in the table below.

Palabra reservadaReserved word Tipo con aliasAliased type
sbyte System.SByte
byte System.Byte
short System.Int16
ushort System.UInt16
int System.Int32
uint System.UInt32
long System.Int64
ulong System.UInt64
char System.Char
float System.Single
double System.Double
bool System.Boolean
decimal System.Decimal

Dado que un tipo simple incluye un alias para un tipo de estructura, cada tipo simple tiene miembros.Because a simple type aliases a struct type, every simple type has members. Por ejemplo, int tiene los miembros declarados en System.Int32 y los miembros heredados de System.Object , y se permiten las siguientes instrucciones:For example, int has the members declared in System.Int32 and the members inherited from System.Object, and the following statements are permitted:

int i = int.MaxValue;           // System.Int32.MaxValue constant
string s = i.ToString();        // System.Int32.ToString() instance method
string t = 123.ToString();      // System.Int32.ToString() instance method

Los tipos simples se diferencian de otros tipos struct en que permiten determinadas operaciones adicionales:The simple types differ from other struct types in that they permit certain additional operations:

  • La mayoría de los tipos simples permiten crear valores escribiendo literales (literales).Most simple types permit values to be created by writing literals (Literals). Por ejemplo, 123 es un literal de tipo int y 'a' es un literal de tipo char .For example, 123 is a literal of type int and 'a' is a literal of type char. C# no hace ningún aprovisionamiento de los literales de tipos struct en general, y los valores no predeterminados de otros tipos struct siempre se crean en última instancia mediante constructores de instancias de esos tipos de estructura.C# makes no provision for literals of struct types in general, and non-default values of other struct types are ultimately always created through instance constructors of those struct types.
  • Cuando los operandos de una expresión son constantes de tipo simple, es posible que el compilador evalúe la expresión en tiempo de compilación.When the operands of an expression are all simple type constants, it is possible for the compiler to evaluate the expression at compile-time. Este tipo de expresión se conoce como constant_expression (expresiones constantes).Such an expression is known as a constant_expression (Constant expressions). Las expresiones que implican operadores definidos por otros tipos struct no se consideran expresiones constantes.Expressions involving operators defined by other struct types are not considered to be constant expressions.
  • A través const de las declaraciones, es posible declarar constantes de los tipos simples (constantes).Through const declarations it is possible to declare constants of the simple types (Constants). No es posible tener constantes de otros tipos struct, pero los campos proporcionan un efecto similar static readonly .It is not possible to have constants of other struct types, but a similar effect is provided by static readonly fields.
  • Las conversiones que implican tipos simples pueden participar en la evaluación de operadores de conversión definidos por otros tipos de struct, pero un operador de conversión definido por el usuario nunca puede participar en la evaluación de otro operador definido por el usuario (evaluación de conversiones definidas por el usuario).Conversions involving simple types can participate in evaluation of conversion operators defined by other struct types, but a user-defined conversion operator can never participate in evaluation of another user-defined operator (Evaluation of user-defined conversions).

Tipos enterosIntegral types

C# admite nueve tipos enteros: sbyte , byte , short , ushort , int , uint , long , ulong y char .C# supports nine integral types: sbyte, byte, short, ushort, int, uint, long, ulong, and char. Los tipos enteros tienen los siguientes tamaños y rangos de valores:The integral types have the following sizes and ranges of values:

  • El sbyte tipo representa enteros de 8 bits con signo con valores comprendidos entre-128 y 127.The sbyte type represents signed 8-bit integers with values between -128 and 127.
  • El byte tipo representa enteros de 8 bits sin signo con valores comprendidos entre 0 y 255.The byte type represents unsigned 8-bit integers with values between 0 and 255.
  • El short tipo representa enteros de 16 bits con signo con valores comprendidos entre-32768 y 32767.The short type represents signed 16-bit integers with values between -32768 and 32767.
  • El ushort tipo representa enteros de 16 bits sin signo con valores comprendidos entre 0 y 65535.The ushort type represents unsigned 16-bit integers with values between 0 and 65535.
  • El int tipo representa enteros de 32 bits con signo con valores comprendidos entre-2147483648 y 2147483647.The int type represents signed 32-bit integers with values between -2147483648 and 2147483647.
  • El uint tipo representa enteros de 32 bits sin signo con valores comprendidos entre 0 y 4294967295.The uint type represents unsigned 32-bit integers with values between 0 and 4294967295.
  • El long tipo representa enteros de 64 bits con signo con valores comprendidos entre-9223372036854775808 y 9223372036854775807.The long type represents signed 64-bit integers with values between -9223372036854775808 and 9223372036854775807.
  • El ulong tipo representa enteros de 64 bits sin signo con valores comprendidos entre 0 y 18446744073709551615.The ulong type represents unsigned 64-bit integers with values between 0 and 18446744073709551615.
  • El char tipo representa enteros de 16 bits sin signo con valores comprendidos entre 0 y 65535.The char type represents unsigned 16-bit integers with values between 0 and 65535. El conjunto de valores posibles para el tipo char corresponde al juego de caracteres Unicode.The set of possible values for the char type corresponds to the Unicode character set. Aunque char tiene la misma representación que ushort , no todas las operaciones permitidas en un tipo se permiten en el otro.Although char has the same representation as ushort, not all operations permitted on one type are permitted on the other.

Los operadores unarios y binarios de tipo entero siempre operan con una precisión de 32 bits con signo, una precisión de 32 bits sin signo, una precisión de 64 con signo o una precisión de bit 64 sin signo:The integral-type unary and binary operators always operate with signed 32-bit precision, unsigned 32-bit precision, signed 64-bit precision, or unsigned 64-bit precision:

  • En el caso de los operadores unario + y ~ , el operando se convierte al tipo T , donde T es el primero de int ,, uint long y ulong que puede representar completamente todos los valores posibles del operando.For the unary + and ~ operators, the operand is converted to type T, where T is the first of int, uint, long, and ulong that can fully represent all possible values of the operand. La operación se realiza entonces con la precisión del tipo T y el tipo del resultado es T .The operation is then performed using the precision of type T, and the type of the result is T.
  • Para el operador unario - , el operando se convierte al tipo T , donde T es el primero de int y long que puede representar completamente todos los valores posibles del operando.For the unary - operator, the operand is converted to type T, where T is the first of int and long that can fully represent all possible values of the operand. La operación se realiza entonces con la precisión del tipo T y el tipo del resultado es T .The operation is then performed using the precision of type T, and the type of the result is T. El operador unario - no se puede aplicar a operandos de tipo ulong .The unary - operator cannot be applied to operands of type ulong.
  • En el caso de los operadores binarios + ,,,,,,,,,, - * / % & ^ | == != > , < , y >= <= , los operandos se convierten al tipo T , donde T es el primero de int , uint , y, long ulong que puede representar por completo todos los valores posibles de ambos operandos.For the binary +, -, *, /, %, &, ^, |, ==, !=, >, <, >=, and <= operators, the operands are converted to type T, where T is the first of int, uint, long, and ulong that can fully represent all possible values of both operands. La operación se realiza entonces con la precisión del tipo T y el tipo del resultado es T (o bool para los operadores relacionales).The operation is then performed using the precision of type T, and the type of the result is T (or bool for the relational operators). No se permite que un operando sea de tipo long y el otro para ser de tipo ulong con los operadores binarios.It is not permitted for one operand to be of type long and the other to be of type ulong with the binary operators.
  • En el caso de los operadores binarios << y >> , el operando izquierdo se convierte al tipo T , donde T es el primero de int ,, y, uint long ulong que puede representar completamente todos los valores posibles del operando.For the binary << and >> operators, the left operand is converted to type T, where T is the first of int, uint, long, and ulong that can fully represent all possible values of the operand. La operación se realiza entonces con la precisión del tipo T y el tipo del resultado es T .The operation is then performed using the precision of type T, and the type of the result is T.

El char tipo se clasifica como un tipo entero, pero difiere de los demás tipos enteros de dos maneras:The char type is classified as an integral type, but it differs from the other integral types in two ways:

  • No hay ninguna conversión implícita de otros tipos al tipo char.There are no implicit conversions from other types to the char type. En concreto, aunque los sbyte tipos, byte y ushort tienen intervalos de valores que se pueden representar completamente con el char tipo, las conversiones implícitas de sbyte , byte o ushort char no existen.In particular, even though the sbyte, byte, and ushort types have ranges of values that are fully representable using the char type, implicit conversions from sbyte, byte, or ushort to char do not exist.
  • Las constantes del char tipo deben escribirse como character_literal s o como integer_literal s en combinación con una conversión al tipo char .Constants of the char type must be written as character_literal s or as integer_literal s in combination with a cast to type char. Por ejemplo, (char)10 es lo mismo que '\x000A'.For example, (char)10 is the same as '\x000A'.

Los checked unchecked operadores and y las instrucciones se utilizan para controlar la comprobación de desbordamiento de las operaciones aritméticas de tipo entero y las conversiones (los operadores Checked y unchecked).The checked and unchecked operators and statements are used to control overflow checking for integral-type arithmetic operations and conversions (The checked and unchecked operators). En un checked contexto, un desbordamiento produce un error en tiempo de compilación o provoca System.OverflowException que se produzca una excepción.In a checked context, an overflow produces a compile-time error or causes a System.OverflowException to be thrown. En un unchecked contexto, se omiten los desbordamientos y se descartan los bits de orden superior que no caben en el tipo de destino.In an unchecked context, overflows are ignored and any high-order bits that do not fit in the destination type are discarded.

Tipos de punto flotanteFloating point types

C# admite dos tipos de punto flotante: float y double .C# supports two floating point types: float and double. Los float double tipos y se representan mediante los formatos IEEE 754 de precisión sencilla de 32 bits y de doble precisión de 64 bits, que proporcionan los siguientes conjuntos de valores:The float and double types are represented using the 32-bit single-precision and 64-bit double-precision IEEE 754 formats, which provide the following sets of values:

  • Cero positivo y cero negativo.Positive zero and negative zero. En la mayoría de los casos, cero positivo y cero negativo se comportan exactamente igual que el valor cero simple, pero ciertas operaciones distinguen entre los dos (operador de división).In most situations, positive zero and negative zero behave identically as the simple value zero, but certain operations distinguish between the two (Division operator).
  • Infinito positivo y infinito negativo.Positive infinity and negative infinity. Los infinitos se generan mediante operaciones como la división por cero de un número distinto de cero.Infinities are produced by such operations as dividing a non-zero number by zero. Por ejemplo, 1.0 / 0.0 produce infinito positivo y -1.0 / 0.0 produce infinito negativo.For example, 1.0 / 0.0 yields positive infinity, and -1.0 / 0.0 yields negative infinity.
  • El valor no numérico , a menudo abreviado como Nan.The Not-a-Number value, often abbreviated NaN. Los Nan se generan mediante operaciones de punto flotante no válidas, como la división de cero por cero.NaNs are produced by invalid floating-point operations, such as dividing zero by zero.
  • El conjunto finito de valores distintos de cero del formulario s * m * 2^e , donde s es 1 o-1, y m y e vienen determinados por el tipo de punto flotante determinado: para float , 0 < m < 2^24 y -149 <= e <= 104 , y para double , 0 < m < 2^53 y -1075 <= e <= 970 .The finite set of non-zero values of the form s * m * 2^e, where s is 1 or -1, and m and e are determined by the particular floating-point type: For float, 0 < m < 2^24 and -149 <= e <= 104, and for double, 0 < m < 2^53 and -1075 <= e <= 970. Los números de punto flotante desnormalizados se consideran valores distintos de cero válidos.Denormalized floating-point numbers are considered valid non-zero values.

El float tipo puede representar valores comprendidos entre aproximadamente 1.5 * 10^-45 y 3.4 * 10^38 con una precisión de 7 dígitos.The float type can represent values ranging from approximately 1.5 * 10^-45 to 3.4 * 10^38 with a precision of 7 digits.

El double tipo puede representar valores comprendidos entre aproximadamente 5.0 * 10^-324 y 1.7 × 10^308 con una precisión de 15-16 dígitos.The double type can represent values ranging from approximately 5.0 * 10^-324 to 1.7 × 10^308 with a precision of 15-16 digits.

Si uno de los operandos de un operador binario es de un tipo de punto flotante, el otro operando debe ser de un tipo entero o de un tipo de punto flotante, y la operación se evalúa como sigue:If one of the operands of a binary operator is of a floating-point type, then the other operand must be of an integral type or a floating-point type, and the operation is evaluated as follows:

  • Si uno de los operandos es de un tipo entero, ese operando se convierte en el tipo de punto flotante del otro operando.If one of the operands is of an integral type, then that operand is converted to the floating-point type of the other operand.
  • Después, si alguno de los operandos es de tipo double , el otro operando se convierte en double , la operación se realiza utilizando al menos el double intervalo y la precisión, y el tipo del resultado es double (o bool para los operadores relacionales).Then, if either of the operands is of type double, the other operand is converted to double, the operation is performed using at least double range and precision, and the type of the result is double (or bool for the relational operators).
  • De lo contrario, la operación se realiza utilizando al menos el float intervalo y la precisión, y el tipo del resultado es float (o bool para los operadores relacionales).Otherwise, the operation is performed using at least float range and precision, and the type of the result is float (or bool for the relational operators).

Los operadores de punto flotante, incluidos los operadores de asignación, nunca generan excepciones.The floating-point operators, including the assignment operators, never produce exceptions. En su lugar, en situaciones excepcionales, las operaciones de punto flotante producen cero, infinito o NaN, como se describe a continuación:Instead, in exceptional situations, floating-point operations produce zero, infinity, or NaN, as described below:

  • Si el resultado de una operación de punto flotante es demasiado pequeño para el formato de destino, el resultado de la operación se convierte en cero positivo o negativo.If the result of a floating-point operation is too small for the destination format, the result of the operation becomes positive zero or negative zero.
  • Si el resultado de una operación de punto flotante es demasiado grande para el formato de destino, el resultado de la operación se convierte en infinito positivo o infinito negativo.If the result of a floating-point operation is too large for the destination format, the result of the operation becomes positive infinity or negative infinity.
  • Si una operación de punto flotante no es válida, el resultado de la operación se convierte en NaN.If a floating-point operation is invalid, the result of the operation becomes NaN.
  • Si uno o los dos operandos de una operación de punto flotante son NaN, el resultado de la operación se convierte en NaN.If one or both operands of a floating-point operation is NaN, the result of the operation becomes NaN.

Las operaciones de punto flotante se pueden realizar con una precisión mayor que el tipo de resultado de la operación.Floating-point operations may be performed with higher precision than the result type of the operation. Por ejemplo, algunas arquitecturas de hardware admiten un tipo de punto flotante "extendido" o "Long Double" con un intervalo y una precisión mayores que el double tipo y realizan implícitamente todas las operaciones de punto flotante con este tipo de precisión superior.For example, some hardware architectures support an "extended" or "long double" floating-point type with greater range and precision than the double type, and implicitly perform all floating-point operations using this higher precision type. Solo con un costo excesivo en el rendimiento se pueden realizar estas arquitecturas de hardware para realizar operaciones de punto flotante con menos precisión y, en lugar de requerir una implementación para que se pierda rendimiento y precisión, C# permite usar un tipo de precisión mayor para todas las operaciones de punto flotante.Only at excessive cost in performance can such hardware architectures be made to perform floating-point operations with less precision, and rather than require an implementation to forfeit both performance and precision, C# allows a higher precision type to be used for all floating-point operations. Aparte de ofrecer resultados más precisos, esto rara vez tiene efectos medibles.Other than delivering more precise results, this rarely has any measurable effects. Sin embargo, en las expresiones con el formato x * y / z , donde la multiplicación genera un resultado que está fuera del double intervalo, pero la división posterior devuelve el resultado temporal al double intervalo, el hecho de que la expresión se evalúe en un formato de intervalo más alto puede provocar que se genere un resultado finito en lugar de un infinito.However, in expressions of the form x * y / z, where the multiplication produces a result that is outside the double range, but the subsequent division brings the temporary result back into the double range, the fact that the expression is evaluated in a higher range format may cause a finite result to be produced instead of an infinity.

El tipo decimalThe decimal type

El tipo decimal es un tipo de datos de 128 bits adecuado para cálculos financieros y monetarios.The decimal type is a 128-bit data type suitable for financial and monetary calculations. El decimal tipo puede representar valores comprendidos entre 1.0 * 10^-28 y aproximadamente 7.9 * 10^28 con 28-29 dígitos significativos.The decimal type can represent values ranging from 1.0 * 10^-28 to approximately 7.9 * 10^28 with 28-29 significant digits.

El conjunto finito de valores de tipo decimal tiene el formato (-1)^s * c * 10^-e , donde el signo s es 0 o 1, el coeficiente c lo proporciona 0 <= *c* < 2^96 y la escala e es tal que 0 <= e <= 28 . El decimal tipo no admite ceros con signo, infinitos o Nan.The finite set of values of type decimal are of the form (-1)^s * c * 10^-e, where the sign s is 0 or 1, the coefficient c is given by 0 <= *c* < 2^96, and the scale e is such that 0 <= e <= 28.The decimal type does not support signed zeros, infinities, or NaN's. Un decimal se representa como un entero de 96 bits escalado por una potencia de diez.A decimal is represented as a 96-bit integer scaled by a power of ten. Para decimal s con un valor absoluto menor que 1.0m , el valor es exacto hasta la posición decimal 28, pero no más.For decimals with an absolute value less than 1.0m, the value is exact to the 28th decimal place, but no further. Para decimal s con un valor absoluto mayor o igual que 1.0m , el valor es exacto a 28 o 29 dígitos.For decimals with an absolute value greater than or equal to 1.0m, the value is exact to 28 or 29 digits. Al contrario que float los double tipos de datos y, los números fraccionarios decimales como 0,1 se pueden representar exactamente en la decimal representación.Contrary to the float and double data types, decimal fractional numbers such as 0.1 can be represented exactly in the decimal representation. En las float double representaciones y, estos números suelen ser fracciones infinitas, por lo que las representaciones son más propensas a errores de redondeo.In the float and double representations, such numbers are often infinite fractions, making those representations more prone to round-off errors.

Si uno de los operandos de un operador binario es de tipo decimal , el otro operando debe ser de un tipo entero o de tipo decimal .If one of the operands of a binary operator is of type decimal, then the other operand must be of an integral type or of type decimal. Si hay un operando de tipo entero, se convierte en decimal antes de que se realice la operación.If an integral type operand is present, it is converted to decimal before the operation is performed.

El resultado de una operación con valores de tipo decimal es que resultaría de calcular un resultado exacto (conservando la escala, tal y como se define para cada operador) y, a continuación, redondear para ajustarse a la representación.The result of an operation on values of type decimal is that which would result from calculating an exact result (preserving scale, as defined for each operator) and then rounding to fit the representation. Los resultados se redondean al valor representable más cercano y, cuando un resultado está igualmente cerca de dos valores representables, al valor que tiene un número par en la posición del dígito menos significativo (esto se conoce como "redondeo bancario").Results are rounded to the nearest representable value, and, when a result is equally close to two representable values, to the value that has an even number in the least significant digit position (this is known as "banker's rounding"). Un resultado de cero siempre tiene un signo de 0 y una escala de 0.A zero result always has a sign of 0 and a scale of 0.

Si una operación aritmética decimal produce un valor menor o igual que 5 * 10^-29 en valor absoluto, el resultado de la operación se convierte en cero.If a decimal arithmetic operation produces a value less than or equal to 5 * 10^-29 in absolute value, the result of the operation becomes zero. Si una decimal operación aritmética genera un resultado que es demasiado grande para el decimal formato, System.OverflowException se produce una excepción.If a decimal arithmetic operation produces a result that is too large for the decimal format, a System.OverflowException is thrown.

El decimal tipo tiene mayor precisión pero menor que los tipos de punto flotante.The decimal type has greater precision but smaller range than the floating-point types. Por lo tanto, las conversiones de los tipos de punto flotante a decimal pueden producir excepciones de desbordamiento, y las conversiones de decimal a los tipos de punto flotante podrían provocar la pérdida de precisión.Thus, conversions from the floating-point types to decimal might produce overflow exceptions, and conversions from decimal to the floating-point types might cause loss of precision. Por estos motivos, no existe ninguna conversión implícita entre los tipos de punto flotante y decimal , y sin conversiones explícitas, no es posible mezclar los operandos y el punto flotante decimal en la misma expresión.For these reasons, no implicit conversions exist between the floating-point types and decimal, and without explicit casts, it is not possible to mix floating-point and decimal operands in the same expression.

Tipo boolThe bool type

El bool tipo representa las cantidades lógicas booleanas.The bool type represents boolean logical quantities. Los valores posibles de tipo bool son true y false .The possible values of type bool are true and false.

No existe ninguna conversión estándar entre bool y otros tipos.No standard conversions exist between bool and other types. En concreto, el bool tipo es distinto e independiente de los tipos enteros, y bool no se puede usar un valor en lugar de un valor entero, y viceversa.In particular, the bool type is distinct and separate from the integral types, and a bool value cannot be used in place of an integral value, and vice versa.

En los lenguajes C y C++, un valor entero o de punto flotante cero, o un puntero nulo se puede convertir al valor booleano false , y un valor entero distinto de cero o de punto flotante, o un puntero no nulo se puede convertir al valor booleano true .In the C and C++ languages, a zero integral or floating-point value, or a null pointer can be converted to the boolean value false, and a non-zero integral or floating-point value, or a non-null pointer can be converted to the boolean value true. En C#, estas conversiones se realizan comparando explícitamente un valor entero o de punto flotante en cero, o comparando explícitamente una referencia de objeto a null .In C#, such conversions are accomplished by explicitly comparing an integral or floating-point value to zero, or by explicitly comparing an object reference to null.

Tipos de enumeraciónEnumeration types

Un tipo de enumeración es un tipo distinto con constantes con nombre.An enumeration type is a distinct type with named constants. Cada tipo de enumeración tiene un tipo subyacente, que debe ser byte , sbyte , short , ushort , int , uint long o ulong .Every enumeration type has an underlying type, which must be byte, sbyte, short, ushort, int, uint, long or ulong. El conjunto de valores del tipo de enumeración es el mismo que el conjunto de valores del tipo subyacente.The set of values of the enumeration type is the same as the set of values of the underlying type. Los valores del tipo de enumeración no están restringidos a los valores de las constantes con nombre.Values of the enumeration type are not restricted to the values of the named constants. Los tipos de enumeración se definen mediante declaraciones de enumeración (declaracionesde enumeración).Enumeration types are defined through enumeration declarations (Enum declarations).

Tipos que aceptan valores NULLNullable types

Un tipo que acepta valores NULL puede representar todos los valores de su tipo subyacente más un valor null adicional.A nullable type can represent all values of its underlying type plus an additional null value. Se escribe un tipo que acepta valores NULL T? , donde T es el tipo subyacente.A nullable type is written T?, where T is the underlying type. Esta sintaxis es una abreviatura de System.Nullable<T> y las dos formas se pueden usar indistintamente.This syntax is shorthand for System.Nullable<T>, and the two forms can be used interchangeably.

Un tipo de valor que no acepta valores NULL es un tipo de valor distinto de System.Nullable<T> y su abreviatura T? (para cualquier T ), además de cualquier parámetro de tipo restringido para ser un tipo de valor que no acepta valores NULL (es decir, cualquier parámetro de tipo con una struct restricción).A non-nullable value type conversely is any value type other than System.Nullable<T> and its shorthand T? (for any T), plus any type parameter that is constrained to be a non-nullable value type (that is, any type parameter with a struct constraint). El System.Nullable<T> tipo especifica la restricción de tipo de valor para T (restricciones de parámetro de tipo), lo que significa que el tipo subyacente de un tipo que acepta valores NULL puede ser cualquier tipo de valor que no acepte valores NULL.The System.Nullable<T> type specifies the value type constraint for T (Type parameter constraints), which means that the underlying type of a nullable type can be any non-nullable value type. El tipo subyacente de un tipo que acepta valores NULL no puede ser un tipo que acepta valores NULL ni un tipo de referencia.The underlying type of a nullable type cannot be a nullable type or a reference type. Por ejemplo, int?? y string? son tipos no válidos.For example, int?? and string? are invalid types.

Una instancia de un tipo que acepta valores NULL T? tiene dos propiedades públicas de solo lectura:An instance of a nullable type T? has two public read-only properties:

  • Una HasValue propiedad de tipo boolA HasValue property of type bool
  • Una Value propiedad de tipo TA Value property of type T

Una instancia para la que HasValue es true se dice que no es NULL.An instance for which HasValue is true is said to be non-null. Una instancia que no es null contiene un valor conocido y Value devuelve ese valor.A non-null instance contains a known value and Value returns that value.

Una instancia para la que HasValue es false se dice que es NULL.An instance for which HasValue is false is said to be null. Una instancia null tiene un valor sin definir.A null instance has an undefined value. Al intentar leer la Value de una instancia null, System.InvalidOperationException se produce una excepción.Attempting to read the Value of a null instance causes a System.InvalidOperationException to be thrown. El proceso de acceso a la Value propiedad de una instancia que acepta valores NULL se conoce como desencapsulado.The process of accessing the Value property of a nullable instance is referred to as unwrapping.

Además del constructor predeterminado, todos los tipos que aceptan valores NULL T? tienen un constructor público que toma un único argumento de tipo T .In addition to the default constructor, every nullable type T? has a public constructor that takes a single argument of type T. Dado un valor x de tipo T , una invocación del constructor con el formatoGiven a value x of type T, a constructor invocation of the form

new T?(x)

crea una instancia no NULL de T? para la que la Value propiedad es x .creates a non-null instance of T? for which the Value property is x. El proceso de creación de una instancia no NULL de un tipo que acepta valores NULL para un valor determinado se conoce como ajuste.The process of creating a non-null instance of a nullable type for a given value is referred to as wrapping.

Las conversiones implícitas están disponibles desde el null literal a T? (conversiones de literales null) y de T a T? (conversiones implícitas que aceptan valores NULL).Implicit conversions are available from the null literal to T? (Null literal conversions) and from T to T? (Implicit nullable conversions).

Tipos de referenciaReference types

Un tipo de referencia es un tipo de clase, un tipo de interfaz, un tipo de matriz o un tipo de delegado.A reference type is a class type, an interface type, an array type, or a delegate type.

reference_type
    : class_type
    | interface_type
    | array_type
    | delegate_type
    ;

class_type
    : type_name
    | 'object'
    | 'dynamic'
    | 'string'
    ;

interface_type
    : type_name
    ;

array_type
    : non_array_type rank_specifier+
    ;

non_array_type
    : type
    ;

rank_specifier
    : '[' dim_separator* ']'
    ;

dim_separator
    : ','
    ;

delegate_type
    : type_name
    ;

Un valor de tipo de referencia es una referencia a una *instancia de del tipo, que se conoce como un objeto _ * * *.A reference type value is a reference to an instance _ of the type, the latter known as an _object**. El valor especial null es compatible con todos los tipos de referencia e indica la ausencia de una instancia.The special value null is compatible with all reference types and indicates the absence of an instance.

Tipos de claseClass types

Un tipo de clase define una estructura de datos que contiene miembros de datos (constantes y campos), miembros de función (métodos, propiedades, eventos, indizadores, operadores, constructores de instancias, destructores y constructores estáticos) y tipos anidados.A class type defines a data structure that contains data members (constants and fields), function members (methods, properties, events, indexers, operators, instance constructors, destructors and static constructors), and nested types. Los tipos de clase admiten la herencia, un mecanismo por el que las clases derivadas pueden extender y especializar clases base.Class types support inheritance, a mechanism whereby derived classes can extend and specialize base classes. Las instancias de tipos de clase se crean mediante object_creation_expression s (expresiones de creación de objetos).Instances of class types are created using object_creation_expression s (Object creation expressions).

Los tipos de clase se describen en clases.Class types are described in Classes.

Algunos tipos de clase predefinidos tienen un significado especial en el lenguaje C#, tal y como se describe en la tabla siguiente.Certain predefined class types have special meaning in the C# language, as described in the table below.

Tipo de claseClass type DescripciónDescription
System.Object Última clase base de todos los demás tipos.The ultimate base class of all other types. Vea el tipo de objeto.See The object type.
System.String Tipo de cadena del lenguaje C#.The string type of the C# language. Vea el tipo de cadena.See The string type.
System.ValueType Clase base de todos los tipos de valor.The base class of all value types. Vea el tipo System. ValueType.See The System.ValueType type.
System.Enum La clase base de todos los tipos de enumeración.The base class of all enum types. Vea enumeraciones.See Enums.
System.Array La clase base de todos los tipos de matriz.The base class of all array types. Vea Matrices.See Arrays.
System.Delegate La clase base de todos los tipos de delegado.The base class of all delegate types. Vea delegados.See Delegates.
System.Exception La clase base de todos los tipos de excepción.The base class of all exception types. Vea excepciones.See Exceptions.

El tipo de objetoThe object type

El object tipo de clase es la clase base definitiva de todos los demás tipos.The object class type is the ultimate base class of all other types. Cada tipo de C# deriva directa o indirectamente del object tipo de clase.Every type in C# directly or indirectly derives from the object class type.

La palabra clave object es simplemente un alias para la clase predefinida System.Object .The keyword object is simply an alias for the predefined class System.Object.

Tipo dynamicThe dynamic type

El dynamic tipo, como object , puede hacer referencia a cualquier objeto.The dynamic type, like object, can reference any object. Cuando se aplican operadores a expresiones de tipo dynamic , su resolución se aplaza hasta que se ejecuta el programa.When operators are applied to expressions of type dynamic, their resolution is deferred until the program is run. Por lo tanto, si el operador no se puede aplicar legalmente al objeto al que se hace referencia, no se proporciona ningún error durante la compilación.Thus, if the operator cannot legally be applied to the referenced object, no error is given during compilation. En su lugar, se producirá una excepción cuando se produzca un error en la resolución del operador en tiempo de ejecución.Instead an exception will be thrown when resolution of the operator fails at run-time.

Su finalidad es permitir el enlace dinámico, que se describe en detalle en el enlace dinámico.Its purpose is to allow dynamic binding, which is described in detail in Dynamic binding.

dynamic se considera idéntico a object excepto en los siguientes aspectos:dynamic is considered identical to object except in the following respects:

  • Las operaciones en expresiones de tipo dynamic se pueden enlazar dinámicamente (enlace dinámico).Operations on expressions of type dynamic can be dynamically bound (Dynamic binding).
  • La inferencia de tipos (inferencia de tipos) preferirá dynamic object si ambas son candidatas.Type inference (Type inference) will prefer dynamic over object if both are candidates.

Debido a esta equivalencia, lo siguiente incluye:Because of this equivalence, the following holds:

  • Existe una conversión de identidad implícita entre object y dynamic , y entre los tipos construidos que son iguales al reemplazar dynamic por objectThere is an implicit identity conversion between object and dynamic, and between constructed types that are the same when replacing dynamic with object
  • Las conversiones implícitas y explícitas a y desde object también se aplican a y desde dynamic .Implicit and explicit conversions to and from object also apply to and from dynamic.
  • Las firmas de método que son iguales cuando se reemplaza dynamic con object se consideran la misma firmaMethod signatures that are the same when replacing dynamic with object are considered the same signature
  • dynamicNo se distingue el tipo de object en tiempo de ejecución.The type dynamic is indistinguishable from object at run-time.
  • Una expresión del tipo dynamic se conoce como una expresión dinámica.An expression of the type dynamic is referred to as a dynamic expression.

Tipo stringThe string type

El string tipo es un tipo de clase sellado que hereda directamente de object .The string type is a sealed class type that inherits directly from object. Las instancias de la string clase representan cadenas de caracteres Unicode.Instances of the string class represent Unicode character strings.

Los valores del string tipo pueden escribirse como literales de cadena (literales de cadena).Values of the string type can be written as string literals (String literals).

La palabra clave string es simplemente un alias para la clase predefinida System.String .The keyword string is simply an alias for the predefined class System.String.

Tipos de interfazInterface types

Una interfaz define un contrato.An interface defines a contract. Una clase o estructura que implementa una interfaz debe adherirse a su contrato.A class or struct that implements an interface must adhere to its contract. Una interfaz puede heredar de varias interfaces base, y una clase o estructura puede implementar varias interfaces.An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces.

Los tipos de interfaz se describen en interfaces.Interface types are described in Interfaces.

Tipos de matrizArray types

Una matriz es una estructura de datos que contiene cero o más variables a las que se tiene acceso a través de índices calculados.An array is a data structure that contains zero or more variables which are accessed through computed indices. Las variables contenidas en una matriz, denominadas también elementos de la matriz, son todas del mismo tipo y este tipo se conoce como tipo de elemento de la matriz.The variables contained in an array, also called the elements of the array, are all of the same type, and this type is called the element type of the array.

Los tipos de matriz se describen en matrices.Array types are described in Arrays.

Tipos delegadosDelegate types

Un delegado es una estructura de datos que hace referencia a uno o más métodos.A delegate is a data structure that refers to one or more methods. En el caso de los métodos de instancia, también hace referencia a sus instancias de objeto correspondientes.For instance methods, it also refers to their corresponding object instances.

El equivalente más cercano de un delegado en C o C++ es un puntero a función, pero mientras que un puntero a función solo puede hacer referencia a funciones estáticas, un delegado puede hacer referencia a métodos estáticos y de instancia.The closest equivalent of a delegate in C or C++ is a function pointer, but whereas a function pointer can only reference static functions, a delegate can reference both static and instance methods. En el último caso, el delegado almacena no solo una referencia al punto de entrada del método, sino también una referencia a la instancia de objeto en la que se invoca el método.In the latter case, the delegate stores not only a reference to the method's entry point, but also a reference to the object instance on which to invoke the method.

Los tipos de delegado se describen en delegados.Delegate types are described in Delegates.

Conversiones boxing y unboxingBoxing and unboxing

El concepto de conversión boxing y unboxing es fundamental para el sistema de tipos de C#.The concept of boxing and unboxing is central to C#'s type system. Proporciona un puente entre value_type s y reference_type s permitiendo que cualquier valor de una value_type se convierta al tipo y desde él object .It provides a bridge between value_type s and reference_type s by permitting any value of a value_type to be converted to and from type object. Las conversiones boxing y unboxing permiten una vista unificada del sistema de tipos en el que un valor de cualquier tipo se puede tratar en última instancia como un objeto.Boxing and unboxing enables a unified view of the type system wherein a value of any type can ultimately be treated as an object.

Conversiones BoxingBoxing conversions

Una conversión boxing permite convertir implícitamente un value_type en un reference_type.A boxing conversion permits a value_type to be implicitly converted to a reference_type. Existen las siguientes conversiones Boxing:The following boxing conversions exist:

  • Desde cualquier value_type al tipo object .From any value_type to the type object.
  • Desde cualquier value_type al tipo System.ValueType .From any value_type to the type System.ValueType.
  • Desde cualquier non_nullable_value_type a cualquier interface_type implementado por el value_type.From any non_nullable_value_type to any interface_type implemented by the value_type.
  • Desde cualquier nullable_type a cualquier interface_type implementado por el tipo subyacente de la nullable_type.From any nullable_type to any interface_type implemented by the underlying type of the nullable_type.
  • Desde cualquier enum_type al tipo System.Enum .From any enum_type to the type System.Enum.
  • Desde cualquier nullable_type con un enum_type subyacente al tipo System.Enum .From any nullable_type with an underlying enum_type to the type System.Enum.
  • Tenga en cuenta que una conversión implícita de un parámetro de tipo se ejecutará como conversión boxing si en tiempo de ejecución termina la conversión de un tipo de valor a un tipo de referencia (conversiones implícitas que implican parámetros de tipo).Note that an implicit conversion from a type parameter will be executed as a boxing conversion if at run-time it ends up converting from a value type to a reference type (Implicit conversions involving type parameters).

La conversión boxing de un valor de una non_nullable_value_type consiste en asignar una instancia de objeto y copiar el valor de non_nullable_value_type en esa instancia.Boxing a value of a non_nullable_value_type consists of allocating an object instance and copying the non_nullable_value_type value into that instance.

La conversión boxing de un valor de un nullable_type genera una referencia nula si es el null valor ( HasValue is false ) o el resultado de desencapsular y convertir en Boxing el valor subyacente en caso contrario.Boxing a value of a nullable_type produces a null reference if it is the null value (HasValue is false), or the result of unwrapping and boxing the underlying value otherwise.

El proceso real de conversión boxing de un valor de un non_nullable_value_type se explica mejor al imaginarse la existencia de una clase de conversión boxing genérica, que se comporta como si se hubiese declarado de la siguiente manera:The actual process of boxing a value of a non_nullable_value_type is best explained by imagining the existence of a generic boxing class, which behaves as if it were declared as follows:

sealed class Box<T>: System.ValueType
{
    T value;

    public Box(T t) {
        value = t;
    }
}

La conversión boxing de un valor v de tipo T ahora consiste en ejecutar la expresión new Box<T>(v) y devolver la instancia resultante como un valor de tipo object .Boxing of a value v of type T now consists of executing the expression new Box<T>(v), and returning the resulting instance as a value of type object. Por lo tanto, las instruccionesThus, the statements

int i = 123;
object box = i;

se corresponden conceptualmente conconceptually correspond to

int i = 123;
object box = new Box<int>(i);

Una clase Boxing como Box<T> la anterior no existe realmente y el tipo dinámico de un valor de conversión boxing no es realmente un tipo de clase.A boxing class like Box<T> above doesn't actually exist and the dynamic type of a boxed value isn't actually a class type. En su lugar, un valor con conversión boxing de tipo T tiene el tipo dinámico T y una comprobación de tipos dinámicos mediante el is operador puede simplemente hacer referencia al tipo T .Instead, a boxed value of type T has the dynamic type T, and a dynamic type check using the is operator can simply reference type T. Por ejemplo,For example,

int i = 123;
object box = i;
if (box is int) {
    Console.Write("Box contains an int");
}

dará como resultado la cadena " Box contains an int " en la consola.will output the string "Box contains an int" on the console.

Una conversión boxing implica que se realice una copia del valor al que se va a aplicar la conversión boxing.A boxing conversion implies making a copy of the value being boxed. Esto es diferente de la conversión de un reference_type al tipo object , en el que el valor sigue haciendo referencia a la misma instancia y simplemente se considera como el tipo menos derivado object .This is different from a conversion of a reference_type to type object, in which the value continues to reference the same instance and simply is regarded as the less derived type object. Por ejemplo, dada la declaraciónFor example, given the declaration

struct Point
{
    public int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

las instrucciones siguientesthe following statements

Point p = new Point(10, 10);
object box = p;
p.x = 20;
Console.Write(((Point)box).x);

dará como resultado el valor 10 en la consola de porque la operación de conversión boxing implícita que se produce en la asignación de p a box hace que se copie el valor de p .will output the value 10 on the console because the implicit boxing operation that occurs in the assignment of p to box causes the value of p to be copied. Si Point se hubiera declarado class en su lugar, el valor 20 sería Output porque p y box haría referencia a la misma instancia.Had Point been declared a class instead, the value 20 would be output because p and box would reference the same instance.

Conversiones unboxingUnboxing conversions

Una conversión unboxing permite convertir un reference_type explícitamente en un value_type.An unboxing conversion permits a reference_type to be explicitly converted to a value_type. Existen las siguientes conversiones unboxing:The following unboxing conversions exist:

  • Del tipo object a cualquier value_type.From the type object to any value_type.
  • Del tipo System.ValueType a cualquier value_type.From the type System.ValueType to any value_type.
  • Desde cualquier interface_type a cualquier non_nullable_value_type que implementa la interface_type.From any interface_type to any non_nullable_value_type that implements the interface_type.
  • Desde cualquier interface_type a cualquier nullable_type cuyo tipo subyacente implementa la interface_type.From any interface_type to any nullable_type whose underlying type implements the interface_type.
  • Del tipo System.Enum a cualquier enum_type.From the type System.Enum to any enum_type.
  • Del tipo System.Enum a cualquier nullable_type con un enum_type subyacente.From the type System.Enum to any nullable_type with an underlying enum_type.
  • Tenga en cuenta que una conversión explícita a un parámetro de tipo se ejecutará como una conversión unboxing si en tiempo de ejecución termina la conversión de un tipo de referencia a un tipo de valor (conversiones dinámicas explícitas).Note that an explicit conversion to a type parameter will be executed as an unboxing conversion if at run-time it ends up converting from a reference type to a value type (Explicit dynamic conversions).

Una operación de conversión unboxing a un non_nullable_value_type consiste en comprobar primero que la instancia de objeto es un valor de conversión boxing del non_nullable_value_type especificado y, a continuación, copiar el valor fuera de la instancia.An unboxing operation to a non_nullable_value_type consists of first checking that the object instance is a boxed value of the given non_nullable_value_type, and then copying the value out of the instance.

La conversión unboxing a un nullable_type genera el valor null del nullable_type si el operando de origen es null , o el resultado ajustado de la conversión unboxing de la instancia de objeto en el tipo subyacente de la nullable_type en caso contrario.Unboxing to a nullable_type produces the null value of the nullable_type if the source operand is null, or the wrapped result of unboxing the object instance to the underlying type of the nullable_type otherwise.

Al hacer referencia a la clase de conversión boxing imaginaria descrita en la sección anterior, una conversión unboxing de un objeto box en un value_type T consiste en ejecutar la expresión ((Box<T>)box).value .Referring to the imaginary boxing class described in the previous section, an unboxing conversion of an object box to a value_type T consists of executing the expression ((Box<T>)box).value. Por lo tanto, las instruccionesThus, the statements

object box = 123;
int i = (int)box;

se corresponden conceptualmente conconceptually correspond to

object box = new Box<int>(123);
int i = ((Box<int>)box).value;

Para que una conversión unboxing a una non_nullable_value_type determinada se realice correctamente en tiempo de ejecución, el valor del operando de origen debe ser una referencia a un valor de conversión boxing de ese non_nullable_value_type.For an unboxing conversion to a given non_nullable_value_type to succeed at run-time, the value of the source operand must be a reference to a boxed value of that non_nullable_value_type. Si el operando de origen es null , System.NullReferenceException se produce una excepción.If the source operand is null, a System.NullReferenceException is thrown. Si el operando de origen es una referencia a un objeto incompatible, System.InvalidCastException se produce una excepción.If the source operand is a reference to an incompatible object, a System.InvalidCastException is thrown.

Para que una conversión unboxing a una nullable_type determinada se realice correctamente en tiempo de ejecución, el valor del operando de origen debe ser null o una referencia a un valor de conversión boxing del non_nullable_value_type subyacente de la nullable_type.For an unboxing conversion to a given nullable_type to succeed at run-time, the value of the source operand must be either null or a reference to a boxed value of the underlying non_nullable_value_type of the nullable_type. Si el operando de origen es una referencia a un objeto incompatible, System.InvalidCastException se produce una excepción.If the source operand is a reference to an incompatible object, a System.InvalidCastException is thrown.

Tipos construidosConstructed types

Una declaración de tipo genérico, por sí sola, denota un *tipo genérico sin enlazar, que se usa como "Blueprint" para formar muchos tipos diferentes, por medio de la aplicación de argumentos de tipo.A generic type declaration, by itself, denotes an unbound generic type _ that is used as a "blueprint" to form many different types, by way of applying _type arguments*_. Los argumentos de tipo se escriben entre corchetes angulares ( < y > ) inmediatamente después del nombre del tipo genérico.The type arguments are written within angle brackets (< and >) immediately following the name of the generic type. Un tipo que incluye al menos un argumento de tipo se denomina tipo construido.A type that includes at least one type argument is called a constructed type. Un tipo construido se puede usar en la mayoría de los lugares del lenguaje en el que puede aparecer un nombre de tipo.A constructed type can be used in most places in the language in which a type name can appear. Un tipo genérico sin enlazar solo se puede usar dentro de un _typeof_expression * (el operador typeof).An unbound generic type can only be used within a _typeof_expression* (The typeof operator).

Los tipos construidos también se pueden usar en expresiones como nombres simples (nombres simples) o al obtener acceso a un miembro (acceso a miembros).Constructed types can also be used in expressions as simple names (Simple names) or when accessing a member (Member access).

Cuando se evalúa un namespace_or_type_name , solo se tienen en cuenta los tipos genéricos con el número correcto de parámetros de tipo.When a namespace_or_type_name is evaluated, only generic types with the correct number of type parameters are considered. Por lo tanto, es posible usar el mismo identificador para identificar distintos tipos, siempre que los tipos tengan distintos números de parámetros de tipo.Thus, it is possible to use the same identifier to identify different types, as long as the types have different numbers of type parameters. Esto resulta útil cuando se combinan clases genéricas y no genéricas en el mismo programa:This is useful when mixing generic and non-generic classes in the same program:

namespace Widgets
{
    class Queue {...}
    class Queue<TElement> {...}
}

namespace MyApplication
{
    using Widgets;

    class X
    {
        Queue q1;            // Non-generic Widgets.Queue
        Queue<int> q2;       // Generic Widgets.Queue
    }
}

Un type_name podría identificar un tipo construido aunque no especifique directamente los parámetros de tipo.A type_name might identify a constructed type even though it doesn't specify type parameters directly. Esto puede ocurrir cuando un tipo está anidado dentro de una declaración de clase genérica y el tipo de instancia de la declaración contenedora se usa implícitamente para la búsqueda de nombres (tipos anidados en clases genéricas):This can occur where a type is nested within a generic class declaration, and the instance type of the containing declaration is implicitly used for name lookup (Nested types in generic classes):

class Outer<T>
{
    public class Inner {...}

    public Inner i;                // Type of i is Outer<T>.Inner
}

En código no seguro, no se puede usar un tipo construido como unmanaged_type (tipos de puntero).In unsafe code, a constructed type cannot be used as an unmanaged_type (Pointer types).

Argumentos de tipoType arguments

Cada argumento de una lista de argumentos de tipo es simplemente un tipo.Each argument in a type argument list is simply a type.

type_argument_list
    : '<' type_arguments '>'
    ;

type_arguments
    : type_argument (',' type_argument)*
    ;

type_argument
    : type
    ;

En el código no seguro (código no seguro), un type_argument no puede ser un tipo de puntero.In unsafe code (Unsafe code), a type_argument may not be a pointer type. Cada argumento de tipo debe satisfacer las restricciones en el parámetro de tipo correspondiente (restricciones de parámetro de tipo).Each type argument must satisfy any constraints on the corresponding type parameter (Type parameter constraints).

Tipos abiertos y cerradosOpen and closed types

Todos los tipos se pueden clasificar como * tipos abiertos _ o _ tipos cerrados *.All types can be classified as either open types _ or _closed types**. Un tipo abierto es un tipo que implica parámetros de tipo.An open type is a type that involves type parameters. Más concretamente:More specifically:

  • Un parámetro de tipo define un tipo abierto.A type parameter defines an open type.
  • Un tipo de matriz es un tipo abierto solo si su tipo de elemento es un tipo abierto.An array type is an open type if and only if its element type is an open type.
  • Un tipo construido es un tipo abierto solo si uno o varios de sus argumentos de tipo es un tipo abierto.A constructed type is an open type if and only if one or more of its type arguments is an open type. Un tipo anidado construido es un tipo abierto si y solo si uno o varios de sus argumentos de tipo o los argumentos de tipo de sus tipos contenedores es un tipo abierto.A constructed nested type is an open type if and only if one or more of its type arguments or the type arguments of its containing type(s) is an open type.

Un tipo cerrado es un tipo que no es un tipo abierto.A closed type is a type that is not an open type.

En tiempo de ejecución, todo el código dentro de una declaración de tipos genéricos se ejecuta en el contexto de un tipo construido cerrado que se creó mediante la aplicación de argumentos de tipo a la declaración genérica.At run-time, all of the code within a generic type declaration is executed in the context of a closed constructed type that was created by applying type arguments to the generic declaration. Cada parámetro de tipo dentro del tipo genérico se enlaza a un tipo en tiempo de ejecución determinado.Each type parameter within the generic type is bound to a particular run-time type. El procesamiento en tiempo de ejecución de todas las instrucciones y expresiones siempre se produce con tipos cerrados y los tipos abiertos solo se producen durante el procesamiento en tiempo de compilación.The run-time processing of all statements and expressions always occurs with closed types, and open types occur only during compile-time processing.

Cada tipo construido cerrado tiene su propio conjunto de variables estáticas, que no se comparten con otros tipos construidos cerrados.Each closed constructed type has its own set of static variables, which are not shared with any other closed constructed types. Puesto que no existe un tipo abierto en tiempo de ejecución, no hay variables estáticas asociadas a un tipo abierto.Since an open type does not exist at run-time, there are no static variables associated with an open type. Dos tipos construidos cerrados son del mismo tipo si se construyen a partir del mismo tipo genérico sin enlazar y sus argumentos de tipo correspondientes son del mismo tipo.Two closed constructed types are the same type if they are constructed from the same unbound generic type, and their corresponding type arguments are the same type.

Tipos enlazados y sin enlazarBound and unbound types

El término *tipo sin enlazar _ hace referencia a un tipo no genérico o a un tipo genérico sin enlazar.The term *unbound type _ refers to a non-generic type or an unbound generic type. El término _ Bound Type* hace referencia a un tipo no genérico o a un tipo construido.The term _ bound type* refers to a non-generic type or a constructed type.

Un tipo sin enlazar hace referencia a la entidad declarada por una declaración de tipos.An unbound type refers to the entity declared by a type declaration. Un tipo genérico sin enlazar no es en sí mismo un tipo y no se puede usar como el tipo de una variable, argumento o valor devuelto, o como un tipo base.An unbound generic type is not itself a type, and cannot be used as the type of a variable, argument or return value, or as a base type. La única construcción en la que se puede hacer referencia a un tipo genérico sin enlazar es la typeof expresión (el operador typeof).The only construct in which an unbound generic type can be referenced is the typeof expression (The typeof operator).

Satisfacer restriccionesSatisfying constraints

Siempre que se hace referencia a un tipo construido o a un método genérico, los argumentos de tipo proporcionados se comprueban con las restricciones de parámetro de tipo declaradas en el tipo o método genérico (restricciones de parámetro de tipo).Whenever a constructed type or generic method is referenced, the supplied type arguments are checked against the type parameter constraints declared on the generic type or method (Type parameter constraints). Para cada where cláusula, el argumento de tipo A que se corresponde con el parámetro de tipo con nombre se compara con cada restricción de la manera siguiente:For each where clause, the type argument A that corresponds to the named type parameter is checked against each constraint as follows:

  • Si la restricción es un tipo de clase, un tipo de interfaz o un parámetro de tipo, permita C representar esa restricción con los argumentos de tipo proporcionados que se sustituyen por los parámetros de tipo que aparecen en la restricción.If the constraint is a class type, an interface type, or a type parameter, let C represent that constraint with the supplied type arguments substituted for any type parameters that appear in the constraint. Para satisfacer la restricción, debe ser el caso de que el tipo A se pueda convertir al tipo C mediante una de las siguientes acciones:To satisfy the constraint, it must be the case that type A is convertible to type C by one of the following:
  • Si la restricción es la restricción de tipo de referencia ( class ), el tipo A debe cumplir uno de los siguientes elementos:If the constraint is the reference type constraint (class), the type A must satisfy one of the following:
    • A es un tipo de interfaz, tipo de clase, tipo de delegado o tipo de matriz.A is an interface type, class type, delegate type or array type. Tenga en cuenta que System.ValueType y System.Enum son tipos de referencia que satisfacen esta restricción.Note that System.ValueType and System.Enum are reference types that satisfy this constraint.
    • A es un parámetro de tipo que se sabe que es un tipo de referencia (restricciones de parámetro de tipo).A is a type parameter that is known to be a reference type (Type parameter constraints).
  • Si la restricción es la restricción de tipo de valor ( struct ), el tipo A debe cumplir uno de los siguientes elementos:If the constraint is the value type constraint (struct), the type A must satisfy one of the following:
    • A es un tipo de estructura o un tipo de enumeración, pero no un tipo que acepta valores NULL.A is a struct type or enum type, but not a nullable type. Tenga en cuenta que System.ValueType y System.Enum son tipos de referencia que no cumplen esta restricción.Note that System.ValueType and System.Enum are reference types that do not satisfy this constraint.
    • A es un parámetro de tipo que tiene la restricción de tipo de valor (restricciones de parámetro de tipo).A is a type parameter having the value type constraint (Type parameter constraints).
  • Si la restricción es la restricción del constructor new() , el tipo A no debe ser abstract y debe tener un constructor sin parámetros público.If the constraint is the constructor constraint new(), the type A must not be abstract and must have a public parameterless constructor. Esto se cumple si se cumple una de las siguientes condiciones:This is satisfied if one of the following is true:

Se produce un error en tiempo de compilación si los argumentos de tipo especificados no satisfacen una o varias restricciones de un parámetro de tipo.A compile-time error occurs if one or more of a type parameter's constraints are not satisfied by the given type arguments.

Dado que los parámetros de tipo no se heredan, las restricciones nunca se heredan.Since type parameters are not inherited, constraints are never inherited either. En el ejemplo siguiente, D debe especificar la restricción en su parámetro de tipo T para que T cumpla la restricción impuesta por la clase base B<T> .In the example below, D needs to specify the constraint on its type parameter T so that T satisfies the constraint imposed by the base class B<T>. En cambio, E la clase no necesita especificar una restricción, porque List<T> implementa IEnumerable para any T .In contrast, class E need not specify a constraint, because List<T> implements IEnumerable for any T.

class B<T> where T: IEnumerable {...}

class D<T>: B<T> where T: IEnumerable {...}

class E<T>: B<List<T>> {...}

Parámetros de tipoType parameters

Un parámetro de tipo es un identificador que designa un tipo de valor o un tipo de referencia al que está enlazado el parámetro en tiempo de ejecución.A type parameter is an identifier designating a value type or reference type that the parameter is bound to at run-time.

type_parameter
    : identifier
    ;

Dado que se pueden crear instancias de un parámetro de tipo con muchos argumentos de tipo reales diferentes, los parámetros de tipo tienen operaciones y restricciones ligeramente diferentes a las de otros tipos.Since a type parameter can be instantiated with many different actual type arguments, type parameters have slightly different operations and restrictions than other types. Entre ellos, se incluye:These include:

Como tipo, los parámetros de tipo son únicamente una construcción en tiempo de compilación.As a type, type parameters are purely a compile-time construct. En tiempo de ejecución, cada parámetro de tipo se enlaza a un tipo en tiempo de ejecución que se especificó proporcionando un argumento de tipo a la declaración de tipos genéricos.At run-time, each type parameter is bound to a run-time type that was specified by supplying a type argument to the generic type declaration. Por lo tanto, el tipo de una variable declarada con un parámetro de tipo, en tiempo de ejecución, será un tipo construido cerrado (tipos abiertos y cerrados).Thus, the type of a variable declared with a type parameter will, at run-time, be a closed constructed type (Open and closed types). La ejecución en tiempo de ejecución de todas las instrucciones y expresiones que impliquen parámetros de tipo usa el tipo real que se proporcionó como argumento de tipo para ese parámetro.The run-time execution of all statements and expressions involving type parameters uses the actual type that was supplied as the type argument for that parameter.

Tipos de árbol de expresiónExpression tree types

*Los árboles de expresión _ permiten representar expresiones lambda como estructuras de datos en lugar de código ejecutable.*Expression trees _ permit lambda expressions to be represented as data structures instead of executable code. Los árboles de expresión son valores de _ tipos de árbol de expresión* del formulario System.Linq.Expressions.Expression<D> , donde D es cualquier tipo de delegado.Expression trees are values of _ expression tree types* of the form System.Linq.Expressions.Expression<D>, where D is any delegate type. En el resto de esta especificación, haremos referencia a estos tipos con la abreviatura Expression<D> .For the remainder of this specification we will refer to these types using the shorthand Expression<D>.

Si existe una conversión de una expresión lambda a un tipo de delegado D , también existe una conversión al tipo de árbol de expresión Expression<D> .If a conversion exists from a lambda expression to a delegate type D, a conversion also exists to the expression tree type Expression<D>. Mientras que la conversión de una expresión lambda a un tipo de delegado genera un delegado que hace referencia al código ejecutable de la expresión lambda, la conversión a un tipo de árbol de expresión crea una representación de árbol de expresión de la expresión lambda.Whereas the conversion of a lambda expression to a delegate type generates a delegate that references executable code for the lambda expression, conversion to an expression tree type creates an expression tree representation of the lambda expression.

Los árboles de expresión son representaciones eficaces de datos en memoria de expresiones lambda y hacen que la estructura de la expresión lambda sea transparente y explícita.Expression trees are efficient in-memory data representations of lambda expressions and make the structure of the lambda expression transparent and explicit.

Al igual que un tipo D de delegado, Expression<D> se dice que tiene tipos de parámetro y de valor devuelto, que son los mismos que los de D .Just like a delegate type D, Expression<D> is said to have parameter and return types, which are the same as those of D.

En el ejemplo siguiente se representa una expresión lambda como código ejecutable y como un árbol de expresión.The following example represents a lambda expression both as executable code and as an expression tree. Dado que existe una conversión a Func<int,int> , también existe una conversión a Expression<Func<int,int>> :Because a conversion exists to Func<int,int>, a conversion also exists to Expression<Func<int,int>>:

Func<int,int> del = x => x + 1;                    // Code

Expression<Func<int,int>> exp = x => x + 1;        // Data

Después de estas asignaciones, el delegado del hace referencia a un método que devuelve x + 1 y el árbol de expresión exp hace referencia a una estructura de datos que describe la expresión x => x + 1 .Following these assignments, the delegate del references a method that returns x + 1, and the expression tree exp references a data structure that describes the expression x => x + 1.

La definición exacta del tipo genérico, Expression<D> así como las reglas precisas para construir un árbol de expresión cuando una expresión lambda se convierte en un tipo de árbol de expresión, está fuera del ámbito de esta especificación.The exact definition of the generic type Expression<D> as well as the precise rules for constructing an expression tree when a lambda expression is converted to an expression tree type, are both outside the scope of this specification.

Es importante hacer dos cosas:Two things are important to make explicit:

  • No todas las expresiones lambda se pueden convertir en árboles de expresión.Not all lambda expressions can be converted to expression trees. Por ejemplo, las expresiones lambda con cuerpos de instrucciones y expresiones lambda que contienen expresiones de asignación no se pueden representar.For instance, lambda expressions with statement bodies, and lambda expressions containing assignment expressions cannot be represented. En estos casos, todavía existe una conversión, pero se producirá un error en tiempo de compilación.In these cases, a conversion still exists, but will fail at compile-time. Estas excepciones se detallan en conversiones de funciones anónimas.These exceptions are detailed in Anonymous function conversions.

  • Expression<D> proporciona un método Compile de instancia que genera un delegado de tipo D :Expression<D> offers an instance method Compile which produces a delegate of type D:

    Func<int,int> del2 = exp.Compile();
    

    Al invocar este delegado se produce el código representado por el árbol de expresión que se va a ejecutar.Invoking this delegate causes the code represented by the expression tree to be executed. Por lo tanto, dado que las definiciones anteriores, del y DEL2 son equivalentes, y las dos instrucciones siguientes tendrán el mismo efecto:Thus, given the definitions above, del and del2 are equivalent, and the following two statements will have the same effect:

    int i1 = del(1);
    
    int i2 = del2(1);
    

    Después de ejecutar este código, i1 y i2 ambos tendrán el valor 2 .After executing this code, i1 and i2 will both have the value 2.