TiposTypes

Os tipos da linguagem C# são divididos em duas categorias principais: tipos de valor _ e _tipos de referência*.The types of the C# language are divided into two main categories: value types _ and _reference types*. Os tipos de valor e de referência podem ser tipos genéricos, que usam um ou mais parâmetros _ Type *.Both value types and reference types may be generic types, which take one or more _*type parameters**. Os parâmetros de tipo podem designar tipos de valor e de referência.Type parameters can designate both value types and reference types.

type
    : value_type
    | reference_type
    | type_parameter
    | type_unsafe
    ;

A categoria final dos tipos, ponteiros, está disponível somente em código não seguro.The final category of types, pointers, is available only in unsafe code. Isso é abordado mais detalhadamente em tipos de ponteiro.This is discussed further in Pointer types.

Tipos de valor diferem dos tipos de referência, pois as variáveis dos tipos de valor contêm diretamente seus dados, enquanto as variáveis dos tipos de referência armazenam *referências _ aos seus dados, o último é conhecido 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**. Com os tipos de referência, é possível que duas variáveis referenciem o mesmo objeto e, assim, possíveis para operações em uma variável afetem o objeto referenciado pela outra variável.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. Com tipos de valor, as variáveis têm sua própria cópia dos dados e não é possível que as operações em um afetem a outra.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.

O sistema de tipos do C# é unificado, de modo que um valor de qualquer tipo pode ser tratado como um objeto.C#'s type system is unified such that a value of any type can be treated as an object. Cada tipo no C#, direta ou indiretamente, deriva do tipo de classe object, e object é a classe base definitiva de todos os tipos.Every type in C# directly or indirectly derives from the object class type, and object is the ultimate base class of all types. Os valores de tipos de referência são tratados como objetos simplesmente exibindo os valores como tipo object.Values of reference types are treated as objects simply by viewing the values as type object. Os valores dos tipos de valor são tratados como objetos executando as operações boxing e unboxing (boxing e unboxing).Values of value types are treated as objects by performing boxing and unboxing operations (Boxing and unboxing).

Tipos de valorValue types

Um tipo de valor é um tipo de struct ou um tipo de enumeração.A value type is either a struct type or an enumeration type. O C# fornece um conjunto de tipos de struct predefinidos chamados de tipos simples.C# provides a set of predefined struct types called the simple types. Os tipos simples são identificados por meio de palavras 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
    ;

Ao contrário de uma variável de um tipo de referência, uma variável de um tipo de valor pode conter o valor null somente se o tipo de valor for um tipo anulável.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 não anulável, há um tipo de valor anulável correspondente, indicando o mesmo conjunto de valores, mais o 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.

A atribuição a uma variável de um tipo de valor cria uma cópia do valor que está sendo atribuído.Assignment to a variable of a value type creates a copy of the value being assigned. Isso difere da atribuição a uma variável de um tipo de referência, que copia a referência, mas não o objeto identificado pela referência.This differs from assignment to a variable of a reference type, which copies the reference but not the object identified by the reference.

O tipo System. ValueTypeThe System.ValueType type

Todos os tipos de valor herdam implicitamente da classe System.ValueType , que, por sua vez, herda da classe object .All value types implicitly inherit from the class System.ValueType, which, in turn, inherits from class object. Não é possível que qualquer tipo seja derivado de um tipo de valor, e tipos de valor são, portanto, lacrados implicitamente (classes lacradas).It is not possible for any type to derive from a value type, and value types are thus implicitly sealed (Sealed classes).

Observe que System.ValueType não é um value_type.Note that System.ValueType is not itself a value_type. Em vez disso, é uma class_type da qual todas as value_type s são derivadas automaticamente.Rather, it is a class_type from which all value_type s are automatically derived.

Construtores padrãoDefault constructors

Todos os tipos de valor declaram implicitamente um construtor de instância sem parâmetros públicos chamado de *construtor padrão _.All value types implicitly declare a public parameterless instance constructor called the *default constructor _. O construtor padrão retorna uma instância inicializada em zero conhecida como _ valor padrão* para o tipo de valor:The default constructor returns a zero-initialized instance known as the _ default value* for the value type:

  • Para todos os Simple_Type s, o valor padrão é o valor produzido por um padrão de bit de todos os zeros: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 e ulong , o valor padrão é 0 .For sbyte, byte, short, ushort, int, uint, long, and ulong, the default value is 0.
    • Para char , o valor padrão é '\x0000' .For char, the default value is '\x0000'.
    • Para float , o valor padrão é 0.0f .For float, the default value is 0.0f.
    • Para double , o valor padrão é 0.0d .For double, the default value is 0.0d.
    • Para decimal , o valor padrão é 0.0m .For decimal, the default value is 0.0m.
    • Para bool , o valor padrão é false .For bool, the default value is false.
  • Para um enum_type E , o valor padrão é 0 , convertido para o tipo E .For an enum_type E, the default value is 0, converted to the type E.
  • Para um struct_type, o valor padrão é o valor produzido definindo todos os campos de tipo de valor como seu valor padrão e todos os campos de tipo de referência como 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 um nullable_type o valor padrão é uma instância para a qual a HasValue propriedade é false e a Value propriedade é indefinida.For a nullable_type the default value is an instance for which the HasValue property is false and the Value property is undefined. O valor padrão também é conhecido como o valor nulo do tipo anulável.The default value is also known as the null value of the nullable type.

Como qualquer outro construtor de instância, o construtor padrão de um tipo de valor é invocado usando o new operador.Like any other instance constructor, the default constructor of a value type is invoked using the new operator. Por motivos de eficiência, esse requisito não tem como objetivo realmente fazer com que a implementação gere uma chamada de construtor.For efficiency reasons, this requirement is not intended to actually have the implementation generate a constructor call. No exemplo a seguir, i as variáveis e j são ambas inicializadas como zero.In the example below, variables i and j are both initialized to zero.

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

Como cada tipo de valor implicitamente tem um construtor de instância sem parâmetros público, não é possível que um tipo de struct contenha uma declaração explícita de um construtor sem 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. No entanto, um tipo struct é permitido para declarar construtores de instância com parâmetros (construtores).A struct type is however permitted to declare parameterized instance constructors (Constructors).

Tipos structStruct types

Um tipo de struct é um tipo de valor que pode declarar constantes, campos, métodos, propriedades, indexadores, operadores, construtores de instância, construtores estáticos e tipos aninhados.A struct type is a value type that can declare constants, fields, methods, properties, indexers, operators, instance constructors, static constructors, and nested types. A declaração de tipos de struct é descrita em declarações de struct.The declaration of struct types is described in Struct declarations.

Tipos simplesSimple types

O C# fornece um conjunto de tipos de struct predefinidos chamados de tipos simples.C# provides a set of predefined struct types called the simple types. Os tipos simples são identificados por meio de palavras reservadas, mas essas palavras reservadas são simplesmente aliases para tipos de struct predefinidos no System namespace, conforme descrito na tabela a seguir.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.

Palavra reservadaReserved word Tipo com 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

Como um tipo simples é alias de um tipo struct, cada tipo simples tem membros.Because a simple type aliases a struct type, every simple type has members. Por exemplo, int tem os membros declarados em System.Int32 e os membros herdados de System.Object , e as instruções a seguir são permitidas: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

Os tipos simples diferem de outros tipos de struct, pois permitem determinadas operações adicionais:The simple types differ from other struct types in that they permit certain additional operations:

  • Os tipos mais simples permitem que os valores sejam criados escrevendo literais (literais).Most simple types permit values to be created by writing literals (Literals). Por exemplo, 123 é um literal do tipo int e 'a' é um literal do tipo char .For example, 123 is a literal of type int and 'a' is a literal of type char. O C# não faz provisão para literais de tipos struct em geral, e valores não padrão de outros tipos struct são, por fim, sempre criados por meio de construtores de instância desses tipos struct.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.
  • Quando os operandos de uma expressão são todas constantes de tipo simples, é possível que o compilador avalie a expressão em tempo de compilação.When the operands of an expression are all simple type constants, it is possible for the compiler to evaluate the expression at compile-time. Essa expressão é conhecida como um constant_expression (expressões constantes).Such an expression is known as a constant_expression (Constant expressions). As expressões que envolvem operadores definidos por outros tipos de struct não são consideradas expressões constantes.Expressions involving operators defined by other struct types are not considered to be constant expressions.
  • Por meio const de declarações, é possível declarar constantes dos tipos simples (constantes).Through const declarations it is possible to declare constants of the simple types (Constants). Não é possível ter constantes de outros tipos de struct, mas um efeito semelhante é fornecido por static readonly campos.It is not possible to have constants of other struct types, but a similar effect is provided by static readonly fields.
  • As conversões que envolvem tipos simples podem participar da avaliação de operadores de conversão definidos por outros tipos de struct, mas um operador de conversão definido pelo usuário nunca pode participar da avaliação de outro operador definido pelo usuário (avaliação de conversões definidas pelo usuário).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 integraisIntegral types

O C# dá suporte a nove tipos integrais:,,,,,,, sbyte byte short ushort int uint long ulong e char .C# supports nine integral types: sbyte, byte, short, ushort, int, uint, long, ulong, and char. Os tipos integrais têm os seguintes tamanhos e intervalos de valores:The integral types have the following sizes and ranges of values:

  • O sbyte tipo representa os inteiros de 8 bits assinados com valores entre-128 e 127.The sbyte type represents signed 8-bit integers with values between -128 and 127.
  • O byte tipo representa inteiros de 8 bits não assinados com valores entre 0 e 255.The byte type represents unsigned 8-bit integers with values between 0 and 255.
  • O short tipo representa os inteiros de 16 bits assinados com valores entre-32768 e 32767.The short type represents signed 16-bit integers with values between -32768 and 32767.
  • O ushort tipo representa inteiros de 16 bits não assinados com valores entre 0 e 65535.The ushort type represents unsigned 16-bit integers with values between 0 and 65535.
  • O int tipo representa os inteiros de 32 bits assinados com valores entre-2147483648 e 2147483647.The int type represents signed 32-bit integers with values between -2147483648 and 2147483647.
  • O uint tipo representa inteiros de 32 bits sem sinal com valores entre 0 e 4294967295.The uint type represents unsigned 32-bit integers with values between 0 and 4294967295.
  • O long tipo representa os inteiros de 64 bits assinados com valores entre-9.223.372.036.854.775.808 e 9223372036854775807.The long type represents signed 64-bit integers with values between -9223372036854775808 and 9223372036854775807.
  • O ulong tipo representa inteiros de 64 bits sem sinal com valores entre 0 e 18446744073709551615.The ulong type represents unsigned 64-bit integers with values between 0 and 18446744073709551615.
  • O char tipo representa inteiros de 16 bits não assinados com valores entre 0 e 65535.The char type represents unsigned 16-bit integers with values between 0 and 65535. O conjunto de valores possíveis para o tipo char corresponde ao conjunto de caracteres Unicode.The set of possible values for the char type corresponds to the Unicode character set. Embora char o tenha a mesma representação que ushort , nem todas as operações permitidas em um tipo são permitidas no outro.Although char has the same representation as ushort, not all operations permitted on one type are permitted on the other.

Os operadores unários e binários de tipo integral sempre operam com precisão de 32 bits assinada, precisão de 32 bits sem sinal, precisão de 64 bits assinada ou precisão de 64 bits não assinado: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:

  • Para unários + e ~ operadores, o operando é convertido em tipo T , em que T é o primeiro de int , uint , long , e ulong que pode representar totalmente todos os valores possíveis do 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. Em seguida, a operação é executada usando a precisão do tipo T e o tipo do resultado é T .The operation is then performed using the precision of type T, and the type of the result is T.
  • Para o operador unário - , o operando é convertido em tipo T , em que T é o primeiro de int e long que pode representar totalmente todos os valores possíveis do 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. Em seguida, a operação é executada usando a precisão do tipo T e o tipo do resultado é T .The operation is then performed using the precision of type T, and the type of the result is T. O operador unário - não pode ser aplicado a operandos do tipo ulong .The unary - operator cannot be applied to operands of type ulong.
  • Para os operadores Binary,,,,,,,,,, + - * ,, / % & ^ | == != > < >= e <= , os operandos são convertidos em tipo T , em que T é o primeiro de int , uint , long e ulong que pode representar totalmente todos os valores possíveis de ambos os 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. Em seguida, a operação é executada usando a precisão do tipo T e o tipo do resultado é T (ou bool para os operadores relacionais).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). Não é permitido que um operando seja do tipo long e o outro seja do tipo ulong com os operadores binários.It is not permitted for one operand to be of type long and the other to be of type ulong with the binary operators.
  • Para o binário << e os >> operadores, o operando esquerdo é convertido em tipo T , em que T é o primeiro de int ,,, uint long e ulong que pode representar totalmente todos os valores possíveis do 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. Em seguida, a operação é executada usando a precisão do tipo T e o tipo do resultado é T .The operation is then performed using the precision of type T, and the type of the result is T.

O char tipo é classificado como um tipo integral, mas difere dos outros tipos integrais de duas maneiras:The char type is classified as an integral type, but it differs from the other integral types in two ways:

  • Não há conversões implícitas de outros tipos para o char tipo.There are no implicit conversions from other types to the char type. Em particular, embora os sbyte tipos, byte e ushort tenham intervalos de valores que são totalmente representáveis usando o char tipo, conversões implícitas de sbyte , byte ou ushort para char não existir.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.
  • As constantes do char tipo devem ser gravadas como character_literal s ou como integer_literal s em combinação com uma conversão para 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 exemplo, (char)10 é o mesmo que '\x000A'.For example, (char)10 is the same as '\x000A'.

Os checked operadores e as unchecked instruções são usados para controlar a verificação de estouro para operações aritméticas de tipo integral e conversões (os operadores marcados e desmarcados).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). Em um checked contexto, um estouro produz um erro de tempo de compilação ou faz com que um seja System.OverflowException gerado.In a checked context, an overflow produces a compile-time error or causes a System.OverflowException to be thrown. Em um unchecked contexto, os estouros são ignorados e quaisquer bits de ordem superior que não couberem no tipo de destino serão descartados.In an unchecked context, overflows are ignored and any high-order bits that do not fit in the destination type are discarded.

Tipos de ponto flutuanteFloating point types

O C# dá suporte a dois tipos de ponto flutuante: float e double .C# supports two floating point types: float and double. Os float double tipos e são representados usando os formatos IEEE 754 de precisão única de 32 bits e de precisão dupla de 64 bits, que fornecem os seguintes 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:

  • Zero positivo e zero negativo.Positive zero and negative zero. Na maioria das situações, zero positivo e zero negativo se comportam de forma idêntica ao valor zero simples, mas determinadas operações distinguem entre os dois (operador de divisão).In most situations, positive zero and negative zero behave identically as the simple value zero, but certain operations distinguish between the two (Division operator).
  • Infinity positivo e infinito negativo.Positive infinity and negative infinity. Os infinitos são produzidos por operações como a divisão de um número diferente de zero por zero.Infinities are produced by such operations as dividing a non-zero number by zero. Por exemplo, 1.0 / 0.0 produz infinito positivo e -1.0 / 0.0 produz infinito negativo.For example, 1.0 / 0.0 yields positive infinity, and -1.0 / 0.0 yields negative infinity.
  • O valor não-a-numérico , geralmente abreviado como NaN.The Not-a-Number value, often abbreviated NaN. NaNs são produzidos por operações de ponto flutuante inválidas, como a divisão de zero por zero.NaNs are produced by invalid floating-point operations, such as dividing zero by zero.
  • O conjunto finito de valores diferentes de zero do formulário s * m * 2^e , em que s é 1 ou-1, e m e e são determinados pelo tipo de ponto flutuante específico: para float , e 0 < m < 2^24 e -149 <= e <= 104 para double , 0 < m < 2^53 e -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. Números de ponto flutuante desnormalizados são considerados valores não zero válidos.Denormalized floating-point numbers are considered valid non-zero values.

O float tipo pode representar valores que variam de aproximadamente 1.5 * 10^-45 a 3.4 * 10^38 com uma precisão 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.

O double tipo pode representar valores que variam de aproximadamente 5.0 * 10^-324 a 1.7 × 10^308 com uma precisão 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.

Se um dos operandos de um operador binário for de um tipo de ponto flutuante, o outro operando deverá ser de um tipo integral ou de um tipo de ponto flutuante, e a operação será avaliada da seguinte maneira: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:

  • Se um dos operandos for de um tipo integral, esse operando será convertido no tipo de ponto flutuante do outro 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.
  • Em seguida, se qualquer um dos operandos for do tipo double , o outro operando será convertido em double , a operação será executada usando pelo menos double intervalo e precisão, e o tipo do resultado será double (ou bool para os operadores relacionais).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).
  • Caso contrário, a operação é executada usando pelo menos float intervalo e precisão, e o tipo do resultado é float (ou bool para os operadores relacionais).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).

Os operadores de ponto flutuante, incluindo os operadores de atribuição, nunca produzem exceções.The floating-point operators, including the assignment operators, never produce exceptions. Em vez disso, em situações excepcionais, as operações de ponto flutuante produzem zero, infinito ou NaN, conforme descrito abaixo:Instead, in exceptional situations, floating-point operations produce zero, infinity, or NaN, as described below:

  • Se o resultado de uma operação de ponto flutuante for muito pequeno para o formato de destino, o resultado da operação se tornará positivo zero ou negativo zero.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.
  • Se o resultado de uma operação de ponto flutuante for muito grande para o formato de destino, o resultado da operação se tornará infinito positivo ou 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.
  • Se uma operação de ponto flutuante for inválida, o resultado da operação se tornará NaN.If a floating-point operation is invalid, the result of the operation becomes NaN.
  • Se um ou ambos os operandos de uma operação de ponto flutuante forem NaN, o resultado da operação se tornará NaN.If one or both operands of a floating-point operation is NaN, the result of the operation becomes NaN.

As operações de ponto flutuante podem ser executadas com precisão mais alta do que o tipo de resultado da operação.Floating-point operations may be performed with higher precision than the result type of the operation. Por exemplo, algumas arquiteturas de hardware dão suporte a um tipo de ponto flutuante "estendido" ou "longo Duplo" com maior intervalo e precisão do que o double tipo e executa implicitamente todas as operações de ponto flutuante usando esse tipo de precisão mais alto.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. Somente o custo excessivo no desempenho pode fazer com que tais arquiteturas de hardware sejam feitas para executar operações de ponto flutuante com menos precisão e, em vez de exigir uma implementação para perder o desempenho e a precisão, o C# permite que um tipo de precisão mais alto seja usado para todas as operações de ponto flutuante.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. Além de fornecer resultados mais precisos, isso raramente tem efeitos mensuráveis.Other than delivering more precise results, this rarely has any measurable effects. No entanto, em expressões do formulário x * y / z , em que a multiplicação produz um resultado fora do double intervalo, mas a divisão subsequente traz o resultado temporário de volta para o double intervalo, o fato de que a expressão é avaliada em um formato de intervalo superior pode fazer com que um resultado finito seja produzido em vez de um 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.

O tipo decimalThe decimal type

O tipo decimal é um tipo de dados de 128 bits adequado para cálculos financeiros e monetários.The decimal type is a 128-bit data type suitable for financial and monetary calculations. O decimal tipo pode representar valores variando de 1.0 * 10^-28 a aproximadamente 7.9 * 10^28 com 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.

O conjunto finito de valores do tipo é decimal do formulário (-1)^s * c * 10^-e , em que o sinal s é 0 ou 1, o coeficiente c é fornecido por 0 <= *c* < 2^96 e a escala e é tal 0 <= e <= 28 . O decimal tipo não dá suporte a zeros assinados, infinitos ou 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. Um decimal é representado como um inteiro de 96 bits dimensionado por uma potência de dez.A decimal is represented as a 96-bit integer scaled by a power of ten. Para decimal s com um valor absoluto menor que 1.0m , o valor é exato para a casa de 28 decimais, mas não mais.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 com um valor absoluto maior ou igual a 1.0m , o valor é exato para 28 ou 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. Ao contrário dos float double tipos de dados e, os números de fração decimais, como 0,1, podem ser representados exatamente na decimal representação.Contrary to the float and double data types, decimal fractional numbers such as 0.1 can be represented exactly in the decimal representation. Nas float double representações e, esses números geralmente são frações infinitas, tornando essas representações mais propensas a erros de arredondamento.In the float and double representations, such numbers are often infinite fractions, making those representations more prone to round-off errors.

Se um dos operandos de um operador binário for do tipo decimal , o outro operando deverá ser de um tipo integral ou do 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. Se um operando de tipo integral estiver presente, ele será convertido em decimal antes que a operação seja executada.If an integral type operand is present, it is converted to decimal before the operation is performed.

O resultado de uma operação em valores do tipo decimal é que isso resultaria no cálculo de um resultado exato (preservando a escala, conforme definido para cada operador) e, em seguida, arredondando para se ajustar à representação.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. Os resultados são arredondados para o valor representável mais próximo e, quando um resultado é igualmente próximo a dois valores representáveis, para o valor que tem um número par na posição de dígito menos significativa (isso é conhecido como "arredondamento do banco").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"). Um resultado zero sempre tem um sinal de 0 e uma escala de 0.A zero result always has a sign of 0 and a scale of 0.

Se uma operação aritmética decimal produzir um valor menor ou igual a 5 * 10^-29 em um valor absoluto, o resultado da operação se tornará zero.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. Se uma decimal operação aritmética produzir um resultado muito grande para o decimal formato, um System.OverflowException será lançado.If a decimal arithmetic operation produces a result that is too large for the decimal format, a System.OverflowException is thrown.

O decimal tipo tem maior precisão, mas um intervalo menor do que os tipos de ponto flutuante.The decimal type has greater precision but smaller range than the floating-point types. Assim, as conversões dos tipos de ponto flutuante decimal podem produzir exceções de estouro, e as conversões de decimal para os tipos de ponto flutuante podem causar perda de precisão.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 esses motivos, não existem conversões implícitas entre os tipos de ponto flutuante e decimal , sem conversões explícitas, não é possível misturar ponto flutuante e decimal operandos na mesma expressão.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.

O tipo boolThe bool type

O bool tipo representa as quantidades lógicas boolianas.The bool type represents boolean logical quantities. Os valores possíveis do tipo bool são true e false .The possible values of type bool are true and false.

Não existem conversões padrão entre os bool outros tipos.No standard conversions exist between bool and other types. Em particular, o bool tipo é distinto e separado dos tipos integrais, e um bool valor não pode ser usado no lugar de um valor integral e vice-versa.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.

Nas linguagens C e C++, um valor integral zero ou de ponto flutuante, ou um ponteiro nulo pode ser convertido para o valor booliano false e um valor de ponto flutuante ou integral diferente de zero, ou um ponteiro não nulo pode ser convertido para o valor booliano 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. No C#, essas conversões são realizadas comparando explicitamente um valor integral ou de ponto flutuante para zero ou comparando explicitamente uma referência de objeto para 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 enumeraçãoEnumeration types

Um tipo de enumeração é um tipo distinto com constantes nomeadas.An enumeration type is a distinct type with named constants. Cada tipo de enumeração tem um tipo subjacente, que deve ser,,,,, byte sbyte short ushort int uint long ou ulong .Every enumeration type has an underlying type, which must be byte, sbyte, short, ushort, int, uint, long or ulong. O conjunto de valores do tipo de enumeração é o mesmo que o conjunto de valores do tipo subjacente.The set of values of the enumeration type is the same as the set of values of the underlying type. Os valores do tipo de enumeração não são restritos aos valores das constantes nomeadas.Values of the enumeration type are not restricted to the values of the named constants. Os tipos de enumeração são definidos por meio de declarações de enumeração (declarações enum).Enumeration types are defined through enumeration declarations (Enum declarations).

Tipos anuláveisNullable types

Um tipo anulável pode representar todos os valores de seu tipo subjacente , além de um valor nulo adicional.A nullable type can represent all values of its underlying type plus an additional null value. Um tipo anulável é gravado T? , em que T é o tipo subjacente.A nullable type is written T?, where T is the underlying type. Essa sintaxe é abreviada para System.Nullable<T> , e os dois formulários podem ser usados de forma intercambiável.This syntax is shorthand for System.Nullable<T>, and the two forms can be used interchangeably.

Um tipo de valor não anulável inversamente é qualquer tipo de valor diferente de System.Nullable<T> e sua abreviação T? (para qualquer T ), além de qualquer parâmetro de tipo restrito a ser um tipo de valor não anulável (ou seja, qualquer parâmetro de tipo com uma struct restrição).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). O System.Nullable<T> tipo especifica a restrição de tipo de valor para T (restrições de parâmetro de tipo), o que significa que o tipo subjacente de um tipo anulável pode ser qualquer tipo de valor não anulável.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. O tipo subjacente de um tipo anulável não pode ser um tipo anulável ou um tipo de referência.The underlying type of a nullable type cannot be a nullable type or a reference type. Por exemplo, int?? e string? são tipos inválidos.For example, int?? and string? are invalid types.

Uma instância de um tipo anulável T? tem duas propriedades públicas somente leitura:An instance of a nullable type T? has two public read-only properties:

  • Uma HasValue Propriedade do tipo boolA HasValue property of type bool
  • Uma Value Propriedade do tipo TA Value property of type T

Uma instância do que HasValue é verdadeira é considerada não nula.An instance for which HasValue is true is said to be non-null. Uma instância não nula contém um valor conhecido e Value retorna esse valor.A non-null instance contains a known value and Value returns that value.

Uma instância do que HasValue é falsa é considerada nula.An instance for which HasValue is false is said to be null. Uma instância nula tem um valor indefinido.A null instance has an undefined value. A tentativa de ler o Value de uma instância nula faz com que um seja System.InvalidOperationException gerado.Attempting to read the Value of a null instance causes a System.InvalidOperationException to be thrown. O processo de acessar a Value propriedade de uma instância anulável é chamado de desencapsulamento.The process of accessing the Value property of a nullable instance is referred to as unwrapping.

Além do construtor padrão, todo tipo anulável T? tem um construtor público que usa um único argumento do 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 um valor x do tipo T , uma invocação de construtor do formulárioGiven a value x of type T, a constructor invocation of the form

new T?(x)

Cria uma instância não nula do T? para a qual a Value propriedade é x .creates a non-null instance of T? for which the Value property is x. O processo de criação de uma instância não nula de um tipo anulável para um determinado valor é chamado de encapsulamento.The process of creating a non-null instance of a nullable type for a given value is referred to as wrapping.

Conversões implícitas estão disponíveis do null literal para T? (conversões de literal NULL) e de T para T? (conversões anuláveis implícitas).Implicit conversions are available from the null literal to T? (Null literal conversions) and from T to T? (Implicit nullable conversions).

Tipos de referênciaReference types

Um tipo de referência é um tipo de classe, um tipo de interface, um tipo de matriz ou um 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
    ;

Um valor de tipo de referência é uma referência a uma *instância _ do tipo, o último conhecido como _ Object *.A reference type value is a reference to an instance _ of the type, the latter known as an _object**. O valor especial null é compatível com todos os tipos de referência e indica a ausência de uma instância.The special value null is compatible with all reference types and indicates the absence of an instance.

Tipos de aulaClass types

Um tipo de classe define uma estrutura de dados que contém membros de dados (constantes e campos), membros de função (métodos, propriedades, eventos, indexadores, operadores, construtores de instância, destruidores e construtores estáticos) e tipos aninhados.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. Os tipos de classe dão suporte à herança, um mecanismo pelo qual classes derivadas podem estender e especializar classes base.Class types support inheritance, a mechanism whereby derived classes can extend and specialize base classes. Instâncias de tipos de classe são criadas usando object_creation_expression s (expressões de criação de objeto).Instances of class types are created using object_creation_expression s (Object creation expressions).

Os tipos de classe são descritos em classes.Class types are described in Classes.

Determinados tipos de classe predefinidos têm significado especial na linguagem C#, conforme descrito na tabela a seguir.Certain predefined class types have special meaning in the C# language, as described in the table below.

Tipo de classeClass type DescriçãoDescription
System.Object A classe base definitiva de todos os outros tipos.The ultimate base class of all other types. Consulte o tipo de objeto.See The object type.
System.String O tipo de cadeia de caracteres da linguagem C#.The string type of the C# language. Consulte o tipo de cadeia de caracteres.See The string type.
System.ValueType A classe base de todos os tipos de valor.The base class of all value types. Consulte o tipo System. ValueType.See The System.ValueType type.
System.Enum A classe base de todos os tipos enum.The base class of all enum types. Consulte enums.See Enums.
System.Array A classe base de todos os tipos de matriz.The base class of all array types. Consulte Matrizes.See Arrays.
System.Delegate A classe base de todos os tipos delegados.The base class of all delegate types. Consulte delegados.See Delegates.
System.Exception A classe base de todos os tipos de exceção.The base class of all exception types. Consulte exceções.See Exceptions.

O tipo de objetoThe object type

O object tipo de classe é a classe base definitiva de todos os outros tipos.The object class type is the ultimate base class of all other types. Todo tipo em C#, direta ou indiretamente, deriva do object tipo de classe.Every type in C# directly or indirectly derives from the object class type.

A palavra-chave object é simplesmente um alias para a classe predefinida System.Object .The keyword object is simply an alias for the predefined class System.Object.

O tipo dinâmicoThe dynamic type

O dynamic tipo, como object , pode fazer referência a qualquer objeto.The dynamic type, like object, can reference any object. Quando os operadores são aplicados a expressões do tipo dynamic , sua resolução é adiada até que o programa seja executado.When operators are applied to expressions of type dynamic, their resolution is deferred until the program is run. Portanto, se o operador não puder ser aplicado legalmente ao objeto referenciado, nenhum erro será fornecido durante a compilação.Thus, if the operator cannot legally be applied to the referenced object, no error is given during compilation. Em vez disso, uma exceção será lançada quando a resolução do operador falhar em tempo de execução.Instead an exception will be thrown when resolution of the operator fails at run-time.

Sua finalidade é permitir a vinculação dinâmica, que é descrita em detalhes na vinculação dinâmica.Its purpose is to allow dynamic binding, which is described in detail in Dynamic binding.

dynamic é considerado idêntico a object , exceto nos seguintes aspectos:dynamic is considered identical to object except in the following respects:

  • As operações em expressões do tipo dynamic podem ser vinculadas dinamicamente (associação dinâmica).Operations on expressions of type dynamic can be dynamically bound (Dynamic binding).
  • A inferência de tipos (inferência de tipos) será preferida dynamic object se ambos forem candidatos.Type inference (Type inference) will prefer dynamic over object if both are candidates.

Devido a essa equivalência, o seguinte contém:Because of this equivalence, the following holds:

  • Há uma conversão de identidade implícita entre object e e dynamic entre os tipos construídos que são iguais ao substituir 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
  • Conversões implícitas e explícitas de e para object também se aplicam a e de dynamic .Implicit and explicit conversions to and from object also apply to and from dynamic.
  • As assinaturas de método que são iguais ao substituir dynamic por object são consideradas a mesma assinaturaMethod signatures that are the same when replacing dynamic with object are considered the same signature
  • O tipo dynamic é indistinguíveis de object em tempo de execução.The type dynamic is indistinguishable from object at run-time.
  • Uma expressão do tipo dynamic é referenciada como uma expressão dinâmica.An expression of the type dynamic is referred to as a dynamic expression.

O tipo de cadeia de caracteresThe string type

O string tipo é um tipo de classe lacrado herdado diretamente do object .The string type is a sealed class type that inherits directly from object. As instâncias da string classe representam as cadeias de caracteres Unicode.Instances of the string class represent Unicode character strings.

Os valores do string tipo podem ser gravados como literais de cadeia de caracteres (literais de cadeia de caracteres).Values of the string type can be written as string literals (String literals).

A palavra-chave string é simplesmente um alias para a classe predefinida System.String .The keyword string is simply an alias for the predefined class System.String.

Tipos de interfaceInterface types

Uma interface define um contrato.An interface defines a contract. Uma classe ou struct que implementa uma interface deve aderir a seu contrato.A class or struct that implements an interface must adhere to its contract. Uma interface pode herdar de várias interfaces base e uma classe ou estrutura pode implementar várias interfaces.An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces.

Os tipos de interface são descritos em interfaces.Interface types are described in Interfaces.

Tipos de matrizArray types

Uma matriz é uma estrutura de dados que contém zero ou mais variáveis que são acessadas por meio de índices computados.An array is a data structure that contains zero or more variables which are accessed through computed indices. As variáveis contidas em uma matriz, também chamadas de elementos da matriz, são todas do mesmo tipo, e esse tipo é chamado de tipo de elemento da 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.

Os tipos de matriz são descritos em matrizes.Array types are described in Arrays.

Tipos delegadosDelegate types

Um delegado é uma estrutura de dados que se refere a um ou mais métodos.A delegate is a data structure that refers to one or more methods. Para métodos de instância, ele também se refere às suas instâncias de objeto correspondentes.For instance methods, it also refers to their corresponding object instances.

O equivalente mais próximo de um delegado em C ou C++ é um ponteiro de função, mas enquanto um ponteiro de função só pode referenciar funções estáticas, um delegado pode fazer referência a métodos estáticos e de instância.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. No último caso, o delegado armazena não apenas uma referência ao ponto de entrada do método, mas também uma referência à instância do objeto na qual invocar o 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.

Os tipos delegados são descritos em delegados.Delegate types are described in Delegates.

Conversão boxing e unboxingBoxing and unboxing

O conceito de boxing e unboxing é fundamental para o sistema de tipos do C#.The concept of boxing and unboxing is central to C#'s type system. Ele fornece uma ponte entre value_type s e reference_type s, permitindo que qualquer valor de uma value_type seja convertido de e para o tipo 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. Boxing e unboxing permitem uma exibição unificada do sistema de tipos, em que um valor de qualquer tipo pode ser tratado, por fim, como um 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.

Conversões de BoxingBoxing conversions

Uma conversão boxing permite que um value_type seja convertido implicitamente em um reference_type.A boxing conversion permits a value_type to be implicitly converted to a reference_type. Existem as seguintes conversões de boxing:The following boxing conversions exist:

  • De qualquer value_type para o tipo object .From any value_type to the type object.
  • De qualquer value_type para o tipo System.ValueType .From any value_type to the type System.ValueType.
  • De qualquer non_nullable_value_type a qualquer interface_type implementada pelo value_type.From any non_nullable_value_type to any interface_type implemented by the value_type.
  • De qualquer nullable_type a qualquer interface_type implementada pelo tipo subjacente do nullable_type.From any nullable_type to any interface_type implemented by the underlying type of the nullable_type.
  • De qualquer enum_type para o tipo System.Enum .From any enum_type to the type System.Enum.
  • De qualquer nullable_type com um enum_type subjacente para o tipo System.Enum .From any nullable_type with an underlying enum_type to the type System.Enum.
  • Observe que uma conversão implícita de um parâmetro de tipo será executada como uma conversão boxing se em tempo de execução acabar convertendo de um tipo de valor para um tipo de referência (conversões implícitas envolvendo 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).

Boxing um valor de uma non_nullable_value_type consiste em alocar uma instância de objeto e copiar o valor de non_nullable_value_type nessa instância.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.

Boxing um valor de uma nullable_type produz uma referência nula se for o null valor ( HasValue is false ), ou o resultado de unquebrad e Boxing o valor subjacente, caso contrário.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.

O processo real de boxing, um valor de uma non_nullable_value_type é mais bem explicado ao imaginar a existência de uma classe Boxing genérica, que se comporta como se fosse declarada da seguinte maneira: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;
    }
}

A Boxing de um valor v do tipo T agora consiste em executar a expressão new Box<T>(v) e retornar a instância resultante como um valor do 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. Portanto, as instruçõesThus, the statements

int i = 123;
object box = i;

corresponde conceitualmente aconceptually correspond to

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

Uma classe Boxing como Box<T> acima não existe de fato e o tipo dinâmico de um valor boxed não é, na verdade, um tipo de classe.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. Em vez disso, um valor em caixa do tipo T tem o tipo dinâmico T e uma verificação de tipo dinâmico usando o is operador pode simplesmente referenciar o 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 exemplo,For example,

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

produzirá a cadeia de caracteres " Box contains an int " no console.will output the string "Box contains an int" on the console.

Uma conversão de Boxing implica fazer uma cópia do valor em caixa.A boxing conversion implies making a copy of the value being boxed. Isso é diferente de uma conversão de um reference_type para tipo object , no qual o valor continua referenciando a mesma instância e simplesmente é considerado o 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 exemplo, dada a declaraçãoFor example, given the declaration

struct Point
{
    public int x, y;

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

as instruções a seguirthe following statements

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

produzirá o valor 10 no console, pois a operação Boxing implícita que ocorre na atribuição de p para box faz com que o valor de seja p copiado.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. PointFoi declarado um class em vez disso, o valor 20 seria output porque p e box faria referência à mesma instância.Had Point been declared a class instead, the value 20 would be output because p and box would reference the same instance.

Conversões de unboxingUnboxing conversions

Uma conversão unboxing permite que um reference_type seja explicitamente convertido em um value_type.An unboxing conversion permits a reference_type to be explicitly converted to a value_type. Existem as seguintes conversões de não conboxing:The following unboxing conversions exist:

  • Do tipo object para qualquer value_type.From the type object to any value_type.
  • Do tipo System.ValueType para qualquer value_type.From the type System.ValueType to any value_type.
  • De qualquer interface_type a qualquer non_nullable_value_type que implemente o interface_type.From any interface_type to any non_nullable_value_type that implements the interface_type.
  • De qualquer interface_type a qualquer nullable_type cujo tipo subjacente implemente o interface_type.From any interface_type to any nullable_type whose underlying type implements the interface_type.
  • Do tipo System.Enum para qualquer enum_type.From the type System.Enum to any enum_type.
  • Do tipo System.Enum para qualquer nullable_type com um enum_type subjacente.From the type System.Enum to any nullable_type with an underlying enum_type.
  • Observe que uma conversão explícita em um parâmetro de tipo será executada como uma conversão sem Boxing se, em tempo de execução, ele terminar a conversão de um tipo de referência para um tipo de valor (conversões 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).

Uma operação de unboxing para um non_nullable_value_type consiste na primeira verificação de que a instância do objeto é um valor em caixa do non_nullable_value_type especificado e, em seguida, copiar o valor para fora da instância.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.

Unboxing para um nullable_type produz o valor nulo do nullable_type se o operando de origem for null ou o resultado encapsulado de uma instância de objeto para o tipo subjacente de nullable_type caso contrário.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.

Fazendo referência à classe de conversão de erros imaginário descrita na seção anterior, uma conversão unboxing de um objeto box em um value_type T consiste em executar a expressão ((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. Portanto, as instruçõesThus, the statements

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

corresponde conceitualmente aconceptually correspond to

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

Para que uma conversão sem Boxing para um determinado non_nullable_value_type seja realizada em tempo de execução, o valor do operando de origem deve ser uma referência a um valor de caixa desse 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. Se o operando de origem for null , um System.NullReferenceException será lançado.If the source operand is null, a System.NullReferenceException is thrown. Se o operando de origem for uma referência a um objeto incompatível, um System.InvalidCastException será gerado.If the source operand is a reference to an incompatible object, a System.InvalidCastException is thrown.

Para que uma conversão sem Boxing para um determinado nullable_type seja realizada em tempo de execução, o valor do operando de origem deve ser null ou uma referência a um valor em caixa da non_nullable_value_type subjacente do 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. Se o operando de origem for uma referência a um objeto incompatível, um System.InvalidCastException será gerado.If the source operand is a reference to an incompatible object, a System.InvalidCastException is thrown.

Tipos construídosConstructed types

Uma declaração de tipo genérico, por si só, denota um tipo genérico desassociado _ que é usado como um "plano gráfico" para formar muitos tipos diferentes, por meio da aplicação 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*. Os argumentos de tipo são gravados entre colchetes angulares ( < e > ) imediatamente após o nome do tipo genérico.The type arguments are written within angle brackets (< and >) immediately following the name of the generic type. Um tipo que inclui pelo menos um argumento de tipo é chamado de tipo construído.A type that includes at least one type argument is called a constructed type. Um tipo construído pode ser usado na maioria dos lugares no idioma em que um nome de tipo pode aparecer.A constructed type can be used in most places in the language in which a type name can appear. Um tipo genérico não associado só pode ser usado dentro de um _typeof_expression * (o operador typeof).An unbound generic type can only be used within a _typeof_expression* (The typeof operator).

Os tipos construídos também podem ser usados em expressões como nomes simples (nomes simples) ou ao acessar um membro (acesso de membro).Constructed types can also be used in expressions as simple names (Simple names) or when accessing a member (Member access).

Quando um namespace_or_type_name é avaliado, somente tipos genéricos com o número correto de parâmetros de tipo são considerados.When a namespace_or_type_name is evaluated, only generic types with the correct number of type parameters are considered. Portanto, é possível usar o mesmo identificador para identificar diferentes tipos, desde que os tipos tenham números diferentes 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. Isso é útil ao misturar classes genéricas e não genéricas no mesmo 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
    }
}

Um type_name pode identificar um tipo construído, mesmo que ele não especifique parâmetros de tipo diretamente.A type_name might identify a constructed type even though it doesn't specify type parameters directly. Isso pode ocorrer quando um tipo é aninhado dentro de uma declaração de classe genérica, e o tipo de instância da declaração recipiente é usado implicitamente para pesquisa de nome (tipos aninhados em classes 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
}

Em código não seguro, um tipo construído não pode ser usado como um unmanaged_type (tipos de ponteiro).In unsafe code, a constructed type cannot be used as an unmanaged_type (Pointer types).

Argumentos de tipoType arguments

Cada argumento em uma lista de argumentos de tipo é simplesmente um 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
    ;

Em código não seguro (código não seguro), um type_argument não pode ser um tipo de ponteiro.In unsafe code (Unsafe code), a type_argument may not be a pointer type. Cada argumento de tipo deve atender a qualquer restrição no parâmetro de tipo correspondente (restrições de parâmetro de tipo).Each type argument must satisfy any constraints on the corresponding type parameter (Type parameter constraints).

Tipos abertos e fechadosOpen and closed types

Todos os tipos podem ser classificados como * tipos abertos _ ou _ tipos fechados *.All types can be classified as either open types _ or _closed types**. Um tipo aberto é um tipo que envolve parâmetros de tipo.An open type is a type that involves type parameters. Mais especificamente:More specifically:

  • Um parâmetro de tipo define um tipo aberto.A type parameter defines an open type.
  • Um tipo de matriz é um tipo aberto se e somente se seu tipo de elemento for um tipo aberto.An array type is an open type if and only if its element type is an open type.
  • Um tipo construído é um tipo aberto se e somente se um ou mais dos seus argumentos de tipo for um tipo aberto.A constructed type is an open type if and only if one or more of its type arguments is an open type. Um tipo aninhado construído é um tipo aberto se e somente se um ou mais dos seus argumentos de tipo ou os argumentos de tipo de seus tipos contiverem um tipo aberto.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.

Um tipo fechado é um tipo que não é um tipo aberto.A closed type is a type that is not an open type.

Em tempo de execução, todo o código dentro de uma declaração de tipo genérico é executado no contexto de um tipo construído fechado que foi criado pela aplicação de argumentos de tipo à declaração 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 do tipo genérico está associado a um tipo de tempo de execução específico.Each type parameter within the generic type is bound to a particular run-time type. O processamento em tempo de execução de todas as instruções e expressões sempre ocorre com tipos fechados e os tipos abertos ocorrem somente durante o processamento de tempo de compilação.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 construído fechado tem seu próprio conjunto de variáveis estáticas, que não são compartilhadas com nenhum outro tipo construído fechado.Each closed constructed type has its own set of static variables, which are not shared with any other closed constructed types. Como um tipo aberto não existe em tempo de execução, não há variáveis estáticas associadas a um tipo aberto.Since an open type does not exist at run-time, there are no static variables associated with an open type. Dois tipos construídos fechados são o mesmo tipo se forem construídos do mesmo tipo genérico não associado e seus argumentos de tipo correspondentes forem do mesmo 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 vinculados e desvinculadosBound and unbound types

O termo *desassociado tipo _ se refere a um tipo não genérico ou a um tipo genérico não associado.The term *unbound type _ refers to a non-generic type or an unbound generic type. O termo _ associado tipo* refere-se a um tipo não genérico ou construído.The term _ bound type* refers to a non-generic type or a constructed type.

Um tipo não associado refere-se à entidade declarada por uma declaração de tipo.An unbound type refers to the entity declared by a type declaration. Um tipo genérico não associado não é, em si, um tipo e não pode ser usado como o tipo de uma variável, um argumento ou um valor de retorno, ou como um 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. A única construção na qual um tipo genérico não associado pode ser referenciado é a typeof expressão (o operador typeof).The only construct in which an unbound generic type can be referenced is the typeof expression (The typeof operator).

Atendendo às restriçõesSatisfying constraints

Sempre que um tipo construído ou um método genérico é referenciado, os argumentos de tipo fornecidos são verificados em relação às restrições de parâmetro de tipo declaradas no tipo ou método genérico (restrições 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, o argumento de tipo A que corresponde ao parâmetro de tipo nomeado é verificado em relação a cada restrição da seguinte maneira:For each where clause, the type argument A that corresponds to the named type parameter is checked against each constraint as follows:

  • Se a restrição for um tipo de classe, um tipo de interface ou um parâmetro de tipo, permita C representar essa restrição com os argumentos de tipo fornecidos substituídos por qualquer parâmetro de tipo que apareça na restrição.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 atender à restrição, ele deve ser o caso em que o tipo A é conversível para digitar C por um dos seguintes:To satisfy the constraint, it must be the case that type A is convertible to type C by one of the following:
  • Se a restrição for a restrição de tipo de referência ( class ), o tipo A deverá satisfazer um dos seguintes:If the constraint is the reference type constraint (class), the type A must satisfy one of the following:
    • A é um tipo de interface, tipo de classe, tipo delegado ou tipo de matriz.A is an interface type, class type, delegate type or array type. Observe que System.ValueType e System.Enum são tipos de referência que atendem a essa restrição.Note that System.ValueType and System.Enum are reference types that satisfy this constraint.
    • A é um parâmetro de tipo que é conhecido como um tipo de referência (restrições de parâmetro de tipo).A is a type parameter that is known to be a reference type (Type parameter constraints).
  • Se a restrição for a restrição de tipo de valor ( struct ), o tipo A deverá satisfazer um dos seguintes:If the constraint is the value type constraint (struct), the type A must satisfy one of the following:
    • A é um tipo de struct ou tipo de enumeração, mas não um tipo anulável.A is a struct type or enum type, but not a nullable type. Observe que System.ValueType e System.Enum são tipos de referência que não atendem a essa restrição.Note that System.ValueType and System.Enum are reference types that do not satisfy this constraint.
    • A é um parâmetro de tipo que tem a restrição de tipo de valor (restrições de parâmetro de tipo).A is a type parameter having the value type constraint (Type parameter constraints).
  • Se a restrição for a restrição de construtor new() , o tipo A não deve ser abstract e deve ter um construtor público sem parâmetros.If the constraint is the constructor constraint new(), the type A must not be abstract and must have a public parameterless constructor. Isso será atendido se uma das seguintes opções for verdadeira:This is satisfied if one of the following is true:

Ocorrerá um erro de tempo de compilação se uma ou mais das restrições de um parâmetro de tipo não forem atendidas pelos argumentos de tipo fornecidos.A compile-time error occurs if one or more of a type parameter's constraints are not satisfied by the given type arguments.

Como os parâmetros de tipo não são herdados, as restrições nunca são herdadas.Since type parameters are not inherited, constraints are never inherited either. No exemplo a seguir, é D necessário especificar a restrição em seu parâmetro de tipo T para que T satisfaça a restrição imposta pela classe 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>. Por outro lado, E a classe não precisa especificar uma restrição, pois 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

Um parâmetro de tipo é um identificador que designa um tipo de valor ou tipo de referência ao qual o parâmetro está associado em tempo de execução.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
    ;

Como um parâmetro de tipo pode ser instanciado com muitos argumentos de tipo real diferentes, os parâmetros de tipo têm operações e restrições ligeiramente diferentes dos outros 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. Elas incluem:These include:

Como um tipo, os parâmetros de tipo são puramente uma construção de tempo de compilação.As a type, type parameters are purely a compile-time construct. Em tempo de execução, cada parâmetro de tipo é associado a um tipo de tempo de execução que foi especificado fornecendo um argumento de tipo para a declaração de tipo genérico.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. Assim, o tipo de uma variável declarada com um parâmetro de tipo será, em tempo de execução, ser um tipo construído fechado (tipos abertos e fechados).Thus, the type of a variable declared with a type parameter will, at run-time, be a closed constructed type (Open and closed types). A execução em tempo de execução de todas as instruções e expressões que envolvem parâmetros de tipo usa o tipo real que foi fornecido como o argumento de tipo para esse 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 árvore de expressãoExpression tree types

*As árvores de expressão _ permitem que as expressões lambda sejam representadas como estruturas de dados em vez de código executável.*Expression trees _ permit lambda expressions to be represented as data structures instead of executable code. As árvores de expressão são valores de tipos de árvore de expressão* do formulário System.Linq.Expressions.Expression<D> , onde D é qualquer 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. Para o restante desta especificação, iremos nos referir a esses tipos usando a abreviação Expression<D> .For the remainder of this specification we will refer to these types using the shorthand Expression<D>.

Se existir uma conversão de uma expressão lambda para um tipo delegado D , uma conversão também existirá para o tipo de árvore de expressão 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>. Enquanto a conversão de uma expressão lambda em um tipo delegado gera um delegado que referencia o código executável para a expressão lambda, a conversão para um tipo de árvore de expressão cria uma representação de árvore de expressão da expressão 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.

As árvores de expressão são representações de dados na memória eficientes de expressões lambda e tornam a estrutura da expressão lambda transparente e explícita.Expression trees are efficient in-memory data representations of lambda expressions and make the structure of the lambda expression transparent and explicit.

Assim como um tipo delegado D , Expression<D> diz-se que os tipos de parâmetro e de retorno são os mesmos do 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.

O exemplo a seguir representa uma expressão lambda tanto como código executável quanto como uma árvore de expressão.The following example represents a lambda expression both as executable code and as an expression tree. Como existe uma conversão para Func<int,int> , uma conversão também existe para 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

Seguindo essas atribuições, o delegado del faz referência a um método que retorna x + 1 , e a árvore de expressão exp faz referência a uma estrutura de dados que descreve a expressão 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.

A definição exata do tipo genérico Expression<D> , bem como as regras precisas para construir uma árvore de expressão quando uma expressão lambda é convertida em um tipo de árvore de expressão, estão fora do escopo desta especificação.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.

Duas coisas são importantes para tornar explícitas:Two things are important to make explicit:

  • Nem todas as expressões lambda podem ser convertidas em árvores de expressão.Not all lambda expressions can be converted to expression trees. Por exemplo, expressões lambda com corpos de instrução e expressões lambda contendo expressões de atribuição não podem ser representadas.For instance, lambda expressions with statement bodies, and lambda expressions containing assignment expressions cannot be represented. Nesses casos, uma conversão ainda existe, mas falhará em tempo de compilação.In these cases, a conversion still exists, but will fail at compile-time. Essas exceções são detalhadas em conversões de função anônimas.These exceptions are detailed in Anonymous function conversions.

  • Expression<D> oferece um método Compile de instância que produz um delegado do tipo D :Expression<D> offers an instance method Compile which produces a delegate of type D:

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

    Invocar esse delegado faz com que o código representado pela árvore de expressão seja executado.Invoking this delegate causes the code represented by the expression tree to be executed. Assim, dadas as definições acima, del e del2 são equivalentes, e as duas instruções a seguir terão o mesmo efeito: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);
    

    Depois de executar esse código i1 , i2 os dois terão o valor 2 .After executing this code, i1 and i2 will both have the value 2.