TypesTypes

Les types du langage C# sont divisés en deux catégories principales : types valeur _ et _types référence*.The types of the C# language are divided into two main categories: value types _ and _reference types*. Les types valeur et les types référence peuvent être des types génériques, qui prennent un ou plusieurs paramètres _ * type * *.Both value types and reference types may be generic types, which take one or more _*type parameters**. Les paramètres de type peuvent désigner à la fois les types valeur et les types référence.Type parameters can designate both value types and reference types.

type
    : value_type
    | reference_type
    | type_parameter
    | type_unsafe
    ;

La catégorie finale de types, pointeurs, est uniquement disponible dans du code unsafe.The final category of types, pointers, is available only in unsafe code. Ce sujet est abordé plus en détail dans types de pointeurs.This is discussed further in Pointer types.

Les types valeur diffèrent des types référence dans le fait que les variables des types valeur contiennent directement leurs données, alors que les variables des types référence stockent *font référence à leurs données, ce dernier étant appelé _ Objects *.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**. Avec les types référence, deux variables peuvent faire référence au même objet et, par conséquent, les opérations sur une variable peuvent affecter l’objet référencé par l’autre 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. Avec les types valeur, les variables disposent chacune de leur propre copie des données, et il n’est pas possible que les opérations sur l’une d’elles affectent l’autre.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.

Le système de type C# est unifié de telle façon qu’une valeur de n’importe quel type peut être traitée en tant qu’objet.C#'s type system is unified such that a value of any type can be treated as an object. Chaque type dans C# dérive directement ou indirectement du type object, et object est la classe de base fondamentale de tous les types.Every type in C# directly or indirectly derives from the object class type, and object is the ultimate base class of all types. Les valeurs des types référence sont considérées comme des objets simplement en affichant les valeurs en tant que type object.Values of reference types are treated as objects simply by viewing the values as type object. Les valeurs des types valeur sont traitées comme des objets en effectuant des opérations de boxing et d’unboxing (boxing et unboxing).Values of value types are treated as objects by performing boxing and unboxing operations (Boxing and unboxing).

Types de valeurValue types

Un type valeur est soit un type struct, soit un type énumération.A value type is either a struct type or an enumeration type. C# fournit un ensemble de types struct prédéfinis appelés types simples.C# provides a set of predefined struct types called the simple types. Les types simples sont identifiés à l’aide de mots réservés.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
    ;

Contrairement à une variable d’un type référence, une variable d’un type valeur peut contenir la valeur null uniquement si le type valeur est un type Nullable.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. Pour chaque type valeur qui n’autorise pas les valeurs NULL, il existe un type valeur Nullable correspondant indiquant le même jeu de valeurs plus la valeur null .For every non-nullable value type there is a corresponding nullable value type denoting the same set of values plus the value null.

L’assignation à une variable d’un type valeur crée une copie de la valeur assignée.Assignment to a variable of a value type creates a copy of the value being assigned. Cela diffère d’une assignation à une variable d’un type référence, qui copie la référence, mais pas l’objet identifié par la référence.This differs from assignment to a variable of a reference type, which copies the reference but not the object identified by the reference.

Type System. ValueTypeThe System.ValueType type

Tous les types valeur héritent implicitement de la classe System.ValueType , qui, à son tour, hérite de la classe object .All value types implicitly inherit from the class System.ValueType, which, in turn, inherits from class object. Il n’est pas possible pour un type de dériver d’un type valeur, et les types valeur sont donc implicitement sealed (classes sealed).It is not possible for any type to derive from a value type, and value types are thus implicitly sealed (Sealed classes).

Notez qu' System.ValueType il ne s’agit pas d’un Value_type.Note that System.ValueType is not itself a value_type. Au lieu de cela, il s’agit d’un class_type duquel tous les Value_type sont dérivés automatiquement.Rather, it is a class_type from which all value_type s are automatically derived.

Constructeurs par défautDefault constructors

Tous les types valeur déclarent implicitement un constructeur d’instance sans paramètre public appelé le *constructeur par défaut _.All value types implicitly declare a public parameterless instance constructor called the *default constructor _. Le constructeur par défaut retourne une instance initialisée à zéro appelée _ valeur par défaut* pour le type de valeur :The default constructor returns a zero-initialized instance known as the _ default value* for the value type:

  • Pour tous les simple_type s, la valeur par défaut est la valeur produite par un modèle binaire de zéros :For all simple_type s, the default value is the value produced by a bit pattern of all zeros:
    • Pour sbyte , byte ,,,,, short ushort int uint long , et ulong , la valeur par défaut est 0 .For sbyte, byte, short, ushort, int, uint, long, and ulong, the default value is 0.
    • Pour char , la valeur par défaut est '\x0000' .For char, the default value is '\x0000'.
    • Pour float , la valeur par défaut est 0.0f .For float, the default value is 0.0f.
    • Pour double , la valeur par défaut est 0.0d .For double, the default value is 0.0d.
    • Pour decimal , la valeur par défaut est 0.0m .For decimal, the default value is 0.0m.
    • Pour bool , la valeur par défaut est false .For bool, the default value is false.
  • Pour un enum_type E , la valeur par défaut est 0 , convertie en type E .For an enum_type E, the default value is 0, converted to the type E.
  • Pour un struct_type, la valeur par défaut est la valeur produite en affectant à tous les champs de type valeur leur valeur par défaut et à tous les champs de type référence la valeur 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.
  • Pour un nullable_type la valeur par défaut est une instance pour laquelle la HasValue propriété a la valeur false et la Value propriété n’est pas définie.For a nullable_type the default value is an instance for which the HasValue property is false and the Value property is undefined. La valeur par défaut est également connue sous le nom de valeur null du type Nullable.The default value is also known as the null value of the nullable type.

Comme tout autre constructeur d’instance, le constructeur par défaut d’un type valeur est appelé à l’aide de l' new opérateur.Like any other instance constructor, the default constructor of a value type is invoked using the new operator. Pour des raisons d’efficacité, cette exigence n’est pas destinée à faire en sorte que l’implémentation génère un appel de constructeur.For efficiency reasons, this requirement is not intended to actually have the implementation generate a constructor call. Dans l’exemple ci-dessous i , j les variables et sont toutes deux initialisées à zéro.In the example below, variables i and j are both initialized to zero.

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

Étant donné que chaque type valeur a implicitement un constructeur d’instance sans paramètre public, il n’est pas possible pour un type struct de contenir une déclaration explicite d’un constructeur sans paramètre.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. Un type struct est toutefois autorisé à déclarer des constructeurs d’instances paramétrables (constructeurs).A struct type is however permitted to declare parameterized instance constructors (Constructors).

Types structStruct types

Un type struct est un type valeur qui peut déclarer des constantes, des champs, des méthodes, des propriétés, des indexeurs, des opérateurs, des constructeurs d’instance, des constructeurs statiques et des types imbriqués.A struct type is a value type that can declare constants, fields, methods, properties, indexers, operators, instance constructors, static constructors, and nested types. La déclaration des types struct est décrite dans déclarations de struct.The declaration of struct types is described in Struct declarations.

Types simplesSimple types

C# fournit un ensemble de types struct prédéfinis appelés types simples.C# provides a set of predefined struct types called the simple types. Les types simples sont identifiés par le biais de mots réservés, mais ces mots réservés sont simplement des alias pour les types struct prédéfinis dans l' System espace de noms, comme décrit dans le tableau ci-dessous.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.

Mot réservéReserved word Type avec 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

Étant donné qu’un type simple est un alias de type struct, chaque type simple a des membres.Because a simple type aliases a struct type, every simple type has members. Par exemple, int a les membres déclarés dans System.Int32 et les membres hérités de System.Object , et les instructions suivantes sont autorisées :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

Les types simples diffèrent des autres types struct en ce qu’ils autorisent des opérations supplémentaires :The simple types differ from other struct types in that they permit certain additional operations:

  • La plupart des types simples autorisent la création de valeurs en écrivant des littéraux (littéraux).Most simple types permit values to be created by writing literals (Literals). Par exemple, 123 est un littéral de type int et 'a' est un littéral de type char .For example, 123 is a literal of type int and 'a' is a literal of type char. C# ne fournit pas de configuration pour les littéraux de types struct en général, et les valeurs autres que celles par défaut des autres types struct sont finalement toujours créées via les constructeurs d’instance de ces types 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.
  • Quand les opérandes d’une expression sont toutes des constantes de type simple, il est possible que le compilateur évalue l’expression au moment de la compilation.When the operands of an expression are all simple type constants, it is possible for the compiler to evaluate the expression at compile-time. Une telle expression est appelée constant_expression (expressions constantes).Such an expression is known as a constant_expression (Constant expressions). Les expressions qui impliquent des opérateurs définis par d’autres types struct ne sont pas considérées comme des expressions constantes.Expressions involving operators defined by other struct types are not considered to be constant expressions.
  • Par const le biais de déclarations, il est possible de déclarer des constantes des types simples (constantes).Through const declarations it is possible to declare constants of the simple types (Constants). Il n’est pas possible d’avoir des constantes d’autres types struct, mais un effet similaire est fourni par les static readonly champs.It is not possible to have constants of other struct types, but a similar effect is provided by static readonly fields.
  • Les conversions impliquant des types simples peuvent participer à l’évaluation des opérateurs de conversion définis par d’autres types struct, mais un opérateur de conversion défini par l’utilisateur ne peut jamais participer à l’évaluation d’un autre opérateur défini par l’utilisateur (évaluation de conversions définies parl’utilisateur).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).

Types intégrauxIntegral types

C# prend en charge neuf types intégraux : sbyte , byte ,,,, short ushort int uint , long , ulong et char .C# supports nine integral types: sbyte, byte, short, ushort, int, uint, long, ulong, and char. Les types intégraux ont les tailles et plages de valeurs suivantes :The integral types have the following sizes and ranges of values:

  • Le sbyte type représente des entiers 8 bits signés dont les valeurs sont comprises entre-128 et 127.The sbyte type represents signed 8-bit integers with values between -128 and 127.
  • Le byte type représente des entiers 8 bits non signés dont la valeur est comprise entre 0 et 255.The byte type represents unsigned 8-bit integers with values between 0 and 255.
  • Le short type représente des entiers 16 bits signés dont les valeurs sont comprises entre-32768 et 32767.The short type represents signed 16-bit integers with values between -32768 and 32767.
  • Le ushort type représente des entiers 16 bits non signés dont la valeur est comprise entre 0 et 65535.The ushort type represents unsigned 16-bit integers with values between 0 and 65535.
  • Le int type représente des entiers 32 bits signés dont les valeurs sont comprises entre-2147483648 et 2147483647.The int type represents signed 32-bit integers with values between -2147483648 and 2147483647.
  • Le uint type représente des entiers 32 bits non signés dont la valeur est comprise entre 0 et 4294967295.The uint type represents unsigned 32-bit integers with values between 0 and 4294967295.
  • Le long type représente des entiers 64 bits signés dont la valeur est comprise entre-9223372036854775808 et 9223372036854775807.The long type represents signed 64-bit integers with values between -9223372036854775808 and 9223372036854775807.
  • Le ulong type représente des entiers 64 bits non signés dont la valeur est comprise entre 0 et 18446744073709551615.The ulong type represents unsigned 64-bit integers with values between 0 and 18446744073709551615.
  • Le char type représente des entiers 16 bits non signés dont la valeur est comprise entre 0 et 65535.The char type represents unsigned 16-bit integers with values between 0 and 65535. Le jeu de valeurs possibles pour le type char correspond au jeu de caractères Unicode.The set of possible values for the char type corresponds to the Unicode character set. Bien que char ait la même représentation que ushort , les opérations autorisées sur un type ne sont pas toutes autorisées sur l’autre.Although char has the same representation as ushort, not all operations permitted on one type are permitted on the other.

Les opérateurs unaires et binaires de type intégral fonctionnent toujours avec la précision 32 bits signée, la précision 32 bits non signée, la précision 64 bits signée ou la précision non signée de 64 bits :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:

  • Pour les opérateurs unaires + et ~ , l’opérande est converti en type T , où T est le premier de int ,, uint long et ulong qui peut représenter entièrement toutes les valeurs possibles de l’opérande.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. L’opération est ensuite effectuée à l’aide de la précision de type T et le type du résultat est T .The operation is then performed using the precision of type T, and the type of the result is T.
  • Pour l’opérateur unaire - , l’opérande est converti en type T , où T est le premier de int et long qui peut représenter entièrement toutes les valeurs possibles de l’opérande.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. L’opération est ensuite effectuée à l’aide de la précision de type T et le type du résultat est T .The operation is then performed using the precision of type T, and the type of the result is T. L’opérateur unaire - ne peut pas être appliqué aux opérandes de type ulong .The unary - operator cannot be applied to operands of type ulong.
  • Pour les opérateurs binaires,,,,,, + - * / % & ^ , | ,, == != , > ,, < >= et <= , les opérandes sont convertis en type T , où T est le premier de int , uint , long et ulong qui peut représenter entièrement toutes les valeurs possibles des deux opérandes.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. L’opération est ensuite effectuée à l’aide de la précision de type T et le type du résultat est T (ou bool pour les opérateurs relationnels).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). Il n’est pas autorisé qu’un opérande soit de type long et que l’autre soit de type ulong avec les opérateurs binaires.It is not permitted for one operand to be of type long and the other to be of type ulong with the binary operators.
  • Pour les opérateurs binaires << et >> , l’opérande de gauche est converti en type T , où T est le premier de int ,, uint long et ulong qui peut représenter entièrement toutes les valeurs possibles de l’opérande.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. L’opération est ensuite effectuée à l’aide de la précision de type T et le type du résultat est T .The operation is then performed using the precision of type T, and the type of the result is T.

Le char type est classé en tant que type intégral, mais il diffère des autres types intégraux de deux manières :The char type is classified as an integral type, but it differs from the other integral types in two ways:

  • Il n’existe pas de conversion implicite d’autres types vers le char type.There are no implicit conversions from other types to the char type. En particulier, même si les sbyte byte types, et ushort ont des plages de valeurs qui sont entièrement représentables à l’aide du char type, les conversions implicites de sbyte , byte ou ushort en char n’existent pas.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.
  • Les constantes du char type doivent être écrites en tant que character_literal s ou en tant que integer_literal s en combinaison avec un cast en type 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. Par exemple, (char)10 est identique à '\x000A'.For example, (char)10 is the same as '\x000A'.

Les checked unchecked opérateurs et et sont utilisés pour contrôler le contrôle de dépassement de capacité pour les opérations arithmétiques de type intégral et les conversions (opérateurs activés et désactivés).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). Dans un checked contexte, un dépassement de capacité génère une erreur au moment de la compilation ou System.OverflowException lève une exception.In a checked context, an overflow produces a compile-time error or causes a System.OverflowException to be thrown. Dans un unchecked contexte, les dépassements de capacité sont ignorés et tous les bits de poids fort qui ne tiennent pas dans le type de destination sont ignorés.In an unchecked context, overflows are ignored and any high-order bits that do not fit in the destination type are discarded.

Types à virgule flottanteFloating point types

C# prend en charge deux types à virgule flottante : float et double .C# supports two floating point types: float and double. Les float double types et sont représentés à l’aide des formats IEEE 754 à double précision 32 bits et 64 bits, qui fournissent les ensembles de valeurs suivants :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:

  • Zéro positif et zéro négatif.Positive zero and negative zero. Dans la plupart des cas, le zéro positif et le zéro négatif se comportent de la même façon que la valeur simple zéro, mais certaines opérations distinguent les deux (opérateur de division).In most situations, positive zero and negative zero behave identically as the simple value zero, but certain operations distinguish between the two (Division operator).
  • Infini positif et infini négatif.Positive infinity and negative infinity. Les infinis sont produits par des opérations telles que la division d’un nombre différent de zéro par zéro.Infinities are produced by such operations as dividing a non-zero number by zero. Par exemple, 1.0 / 0.0 produit l’infini positif et -1.0 / 0.0 produit l’infini négatif.For example, 1.0 / 0.0 yields positive infinity, and -1.0 / 0.0 yields negative infinity.
  • Valeur not-a-Number , souvent abrégée Nan.The Not-a-Number value, often abbreviated NaN. Les valeurs NaN sont produites par des opérations à virgule flottante non valides, telles que la division de zéro par zéro.NaNs are produced by invalid floating-point operations, such as dividing zero by zero.
  • Jeu fini de valeurs non null de la forme s * m * 2^e , où s est 1 ou-1, et m et e sont déterminés par le type à virgule flottante particulier : pour, float 0 < m < 2^24 et -149 <= e <= 104 , et pour double , 0 < m < 2^53 et -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. Les nombres à virgule flottante dénormalisés sont considérés comme des valeurs non nulles valides.Denormalized floating-point numbers are considered valid non-zero values.

Le float type peut représenter des valeurs comprises entre approximativement 1.5 * 10^-45 et 3.4 * 10^38 avec une précision de 7 chiffres.The float type can represent values ranging from approximately 1.5 * 10^-45 to 3.4 * 10^38 with a precision of 7 digits.

Le double type peut représenter des valeurs comprises entre approximativement 5.0 * 10^-324 et 1.7 × 10^308 avec une précision de 15-16 chiffres.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 l’un des opérandes d’un opérateur binaire est d’un type à virgule flottante, l’autre opérande doit être d’un type intégral ou d’un type à virgule flottante, et l’opération est évaluée comme suit :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 l’un des opérandes est d’un type intégral, cet opérande est converti en type à virgule flottante de l’autre opérande.If one of the operands is of an integral type, then that operand is converted to the floating-point type of the other operand.
  • Ensuite, si l’un des opérandes est de type double , l’autre opérande est converti en double , l’opération est effectuée à l’aide d’au moins la double plage et la précision, et le type du résultat est double (ou bool pour les opérateurs relationnels).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).
  • Dans le cas contraire, l’opération est effectuée à l’aide d’au moins la float plage et la précision, et le type du résultat est float (ou bool pour les opérateurs relationnels).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).

Les opérateurs à virgule flottante, y compris les opérateurs d’assignation, ne produisent jamais d’exceptions.The floating-point operators, including the assignment operators, never produce exceptions. À la place, dans des situations exceptionnelles, les opérations à virgule flottante produisent zéro, Infinity ou NaN, comme décrit ci-dessous :Instead, in exceptional situations, floating-point operations produce zero, infinity, or NaN, as described below:

  • Si le résultat d’une opération à virgule flottante est trop petit pour le format de destination, le résultat de l’opération devient un zéro positif ou un zéro négatif.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 le résultat d’une opération à virgule flottante est trop grand pour le format de destination, le résultat de l’opération devient une infini positif ou négatif.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 une opération à virgule flottante n’est pas valide, le résultat de l’opération devient NaN.If a floating-point operation is invalid, the result of the operation becomes NaN.
  • Si l’un ou les deux opérandes d’une opération à virgule flottante sont NaN, le résultat de l’opération devient NaN.If one or both operands of a floating-point operation is NaN, the result of the operation becomes NaN.

Les opérations à virgule flottante peuvent être effectuées avec une précision supérieure à celle du type de résultat de l’opération.Floating-point operations may be performed with higher precision than the result type of the operation. Par exemple, certaines architectures matérielles prennent en charge un type à virgule flottante « étendu » ou « long double » avec une plage et une précision supérieures à celles du double type, et effectuent implicitement toutes les opérations en virgule flottante à l’aide de ce type de précision plus élevée.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. En ce qui concerne uniquement le coût excessif des performances, de telles architectures matérielles peuvent être effectuées pour effectuer des opérations à virgule flottante avec moins de précision, et au lieu d’exiger une implémentation pour perdre à la fois les performances et la précision, C# permet l’utilisation d’un type de précision plus élevé pour toutes les opérations à virgule flottante.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. En dehors de la diffusion de résultats plus précis, cela a rarement des effets mesurables.Other than delivering more precise results, this rarely has any measurable effects. Toutefois, dans les expressions de la forme x * y / z , où la multiplication produit un résultat en dehors de la double plage, mais la Division suivante ramène le résultat temporaire double à la plage, le fait que l’expression soit évaluée dans un format de plage plus élevé peut entraîner la production d’un résultat fini au lieu d’une infini.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.

Type décimalThe decimal type

Le type decimal est un type de données 128 bits adapté aux calculs financiers et monétaires.The decimal type is a 128-bit data type suitable for financial and monetary calculations. Le decimal type peut représenter des valeurs comprises entre 1.0 * 10^-28 et environ 7.9 * 10^28 28-29 chiffres significatifs.The decimal type can represent values ranging from 1.0 * 10^-28 to approximately 7.9 * 10^28 with 28-29 significant digits.

L’ensemble fini de valeurs de type decimal se présente sous la forme (-1)^s * c * 10^-e , où le signe s est 0 ou 1, le coefficient c est donné par 0 <= *c* < 2^96 , et l’échelle e est telle que 0 <= e <= 28 . Le decimal type ne prend pas en charge les zéros, les infinis ou les Nan signés.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 est représenté sous la forme d’un entier 96 bits mis à l’échelle par une puissance de dix.A decimal is represented as a 96-bit integer scaled by a power of ten. Pour les decimal s avec une valeur absolue inférieure à 1.0m , la valeur est exacte jusqu’au 28ème décimal, mais pas plus.For decimals with an absolute value less than 1.0m, the value is exact to the 28th decimal place, but no further. Pour decimal les s avec une valeur absolue supérieure ou égale à 1.0m , la valeur est exacte à 28 ou 29 chiffres.For decimals with an absolute value greater than or equal to 1.0m, the value is exact to 28 or 29 digits. Contrairement aux float types de double données et, les nombres fractionnaires décimaux tels que 0,1 peuvent être représentés exactement dans la decimal représentation.Contrary to the float and double data types, decimal fractional numbers such as 0.1 can be represented exactly in the decimal representation. Dans les float double représentations et, ces nombres sont souvent des fractions infinies, ce qui rend ces représentations plus sujettes aux erreurs d’arrondi.In the float and double representations, such numbers are often infinite fractions, making those representations more prone to round-off errors.

Si l’un des opérandes d’un opérateur binaire est de type decimal , l’autre opérande doit être de type intégral ou de type 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 un opérande de type intégral est présent, il est converti en decimal avant l’exécution de l’opération.If an integral type operand is present, it is converted to decimal before the operation is performed.

Le résultat d’une opération sur des valeurs de type decimal est celui qui résulterait du calcul d’un résultat exact (préservation de l’échelle, tel que défini pour chaque opérateur), puis arrondi pour s’ajuster à la représentation.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. Les résultats sont arrondis à la valeur représentable la plus proche et, lorsqu’un résultat est proche de deux valeurs représentables, à la valeur qui a un nombre pair dans la position de chiffre la moins significative (c’est ce qu’on appelle le « arrondi bancaire »).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 résultat zéro a toujours un signe de 0 et une échelle de 0.A zero result always has a sign of 0 and a scale of 0.

Si une opération arithmétique décimale produit une valeur inférieure ou égale à la 5 * 10^-29 valeur absolue, le résultat de l’opération devient zéro.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 une decimal opération arithmétique produit un résultat trop grand pour le decimal format, une System.OverflowException est levée.If a decimal arithmetic operation produces a result that is too large for the decimal format, a System.OverflowException is thrown.

Le decimal type a une plus grande précision, mais une plage plus petite que les types à virgule flottante.The decimal type has greater precision but smaller range than the floating-point types. Ainsi, les conversions des types à virgule flottante en decimal peuvent générer des exceptions de dépassement de capacité et les conversions de decimal en types à virgule flottante peuvent entraîner une perte de précision.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. Pour ces raisons, il n’existe aucune conversion implicite entre les types à virgule flottante et decimal , et sans casts explicites, il n’est pas possible de mélanger des opérandes à virgule flottante et decimal des opérandes dans la même expression.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.

Type boolThe bool type

Le bool type représente des quantités logiques booléennes.The bool type represents boolean logical quantities. Les valeurs possibles de type bool sont true et false .The possible values of type bool are true and false.

Il n’existe pas de conversion standard entre bool et d’autres types.No standard conversions exist between bool and other types. En particulier, le bool type est distinct et distinct des types intégraux, et une bool valeur ne peut pas être utilisée à la place d’une valeur intégrale, et 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.

Dans les langages C et C++, il s’agit d’une valeur intégrale ou à virgule flottante nulle, ou un pointeur NULL peut être converti en valeur booléenne false , et une valeur intégrale ou à virgule flottante différente de zéro, ou un pointeur non NULL peut être converti en valeur booléenne 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#, ces conversions sont accomplies en comparant explicitement une valeur intégrale ou à virgule flottante à zéro, ou en comparant explicitement une référence d’objet à 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.

Types d'énumérationEnumeration types

Un type énumération est un type distinct avec des constantes nommées.An enumeration type is a distinct type with named constants. Chaque type énumération a un type sous-jacent, qui doit être,,,,, 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. L’ensemble de valeurs du type énumération est le même que l’ensemble de valeurs du type sous-jacent.The set of values of the enumeration type is the same as the set of values of the underlying type. Les valeurs du type d’énumération ne sont pas limitées aux valeurs des constantes nommées.Values of the enumeration type are not restricted to the values of the named constants. Les types énumération sont définis par le biais de déclarations d’énumération (déclarations enum).Enumeration types are defined through enumeration declarations (Enum declarations).

Types NullableNullable types

Un type Nullable peut représenter toutes les valeurs de son type sous-jacent plus une valeur null supplémentaire.A nullable type can represent all values of its underlying type plus an additional null value. Un type Nullable est écrit T? , où T est le type sous-jacent.A nullable type is written T?, where T is the underlying type. Cette syntaxe est raccourcie pour System.Nullable<T> , et les deux formulaires peuvent être utilisés indifféremment.This syntax is shorthand for System.Nullable<T>, and the two forms can be used interchangeably.

Un type valeur qui n’autorise pas les valeurs NULL est inversement tout type valeur autre que System.Nullable<T> et son raccourci T? (pour Any T ), plus tout paramètre de type qui est contrainte comme étant un type valeur non Nullable (autrement dit, tout paramètre de type avec une struct contrainte).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). Le System.Nullable<T> type spécifie la contrainte de type valeur pour T (contraintes de paramètre de type), ce qui signifie que le type sous-jacent d’un type Nullable peut être n’importe quel type valeur n’acceptant pas les valeurs 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. Le type sous-jacent d’un type Nullable ne peut pas être un type Nullable ou un type référence.The underlying type of a nullable type cannot be a nullable type or a reference type. Par exemple, int?? et string? sont des types non valides.For example, int?? and string? are invalid types.

Une instance d’un type Nullable T? a deux propriétés publiques en lecture seule :An instance of a nullable type T? has two public read-only properties:

  • Une HasValue propriété de type boolA HasValue property of type bool
  • Une Value propriété de type TA Value property of type T

Une instance pour laquelle HasValue a la valeur true est dite non null.An instance for which HasValue is true is said to be non-null. Une instance non null contient une valeur connue et Value retourne cette valeur.A non-null instance contains a known value and Value returns that value.

Une instance pour laquelle HasValue a la valeur false est considérée comme étant null.An instance for which HasValue is false is said to be null. Une instance null a une valeur non définie.A null instance has an undefined value. Si vous tentez de lire le Value d’une instance null, une System.InvalidOperationException exception est levée.Attempting to read the Value of a null instance causes a System.InvalidOperationException to be thrown. Le processus d’accès à la Value propriété d’une instance Nullable est appelé désencapsulage.The process of accessing the Value property of a nullable instance is referred to as unwrapping.

En plus du constructeur par défaut, chaque type Nullable T? a un constructeur public qui accepte un argument unique de type T .In addition to the default constructor, every nullable type T? has a public constructor that takes a single argument of type T. À partir d’une valeur x de type T , un appel de constructeur de la formeGiven a value x of type T, a constructor invocation of the form

new T?(x)

crée une instance non null de T? pour laquelle la Value propriété a la valeur x .creates a non-null instance of T? for which the Value property is x. Le processus de création d’une instance non null d’un type Nullable pour une valeur donnée est appelé « Wrapping».The process of creating a non-null instance of a nullable type for a given value is referred to as wrapping.

Les conversions implicites sont disponibles à partir du null littéral vers T? (conversions de littéraux NULL) et de à (conversions T T? Nullable implicites).Implicit conversions are available from the null literal to T? (Null literal conversions) and from T to T? (Implicit nullable conversions).

Types référenceReference types

Un type référence est un type de classe, un type interface, un type tableau ou un type délégué.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
    ;

Une valeur de type référence est une référence à une instance* du type, ce dernier connu sous le nom d'objet _ * * *.A reference type value is a reference to an instance _ of the type, the latter known as an _object**. La valeur spéciale null est compatible avec tous les types de référence et indique l’absence d’une instance.The special value null is compatible with all reference types and indicates the absence of an instance.

Types de classeClass types

Un type de classe définit une structure de données qui contient des données membres (constantes et champs), des fonctions membres (méthodes, propriétés, événements, indexeurs, opérateurs, constructeurs d’instance, destructeurs et constructeurs statiques) et des types imbriqués.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. Les types de classe prennent en charge l’héritage, mécanisme dans lequel les classes dérivées peuvent étendre et spécialiser les classes de base.Class types support inheritance, a mechanism whereby derived classes can extend and specialize base classes. Les instances de types de classe sont créées à l’aide de object_creation_expression s (expressions de création d’objet).Instances of class types are created using object_creation_expression s (Object creation expressions).

Les types de classe sont décrits dans les classes.Class types are described in Classes.

Certains types de classe prédéfinis ont une signification particulière dans le langage C#, comme décrit dans le tableau ci-dessous.Certain predefined class types have special meaning in the C# language, as described in the table below.

Type de classeClass type DescriptionDescription
System.Object Classe de base fondamentale de tous les autres types.The ultimate base class of all other types. Consultez le type d’objet.See The object type.
System.String Type de chaîne du langage C#.The string type of the C# language. Consultez type de chaîne.See The string type.
System.ValueType Classe de base de tous les types valeur.The base class of all value types. Consultez le type System. ValueType.See The System.ValueType type.
System.Enum Classe de base de tous les types ENUM.The base class of all enum types. Consultez enums.See Enums.
System.Array Classe de base de tous les types tableau.The base class of all array types. Consultez Tableaux.See Arrays.
System.Delegate Classe de base de tous les types délégués.The base class of all delegate types. Consultez délégués.See Delegates.
System.Exception Classe de base de tous les types d’exception.The base class of all exception types. Consultez exceptions.See Exceptions.

Type d’objet.The object type

Le object type de classe est la classe de base fondamentale de tous les autres types.The object class type is the ultimate base class of all other types. Chaque type en C# dérive directement ou indirectement du object type de classe.Every type in C# directly or indirectly derives from the object class type.

Le mot clé object est simplement un alias pour la classe prédéfinie System.Object .The keyword object is simply an alias for the predefined class System.Object.

Type dynamiqueThe dynamic type

Le dynamic type, par exemple object , peut faire référence à n’importe quel objet.The dynamic type, like object, can reference any object. Lorsque des opérateurs sont appliqués à des expressions de type dynamic , leur résolution est différée jusqu’à ce que le programme soit exécuté.When operators are applied to expressions of type dynamic, their resolution is deferred until the program is run. Ainsi, si l’opérateur ne peut pas être légalement appliqué à l’objet référencé, aucune erreur n’est donnée durant la compilation.Thus, if the operator cannot legally be applied to the referenced object, no error is given during compilation. Au lieu de cela, une exception est levée lorsque la résolution de l’opérateur échoue au moment de l’exécution.Instead an exception will be thrown when resolution of the operator fails at run-time.

Son objectif est d’autoriser la liaison dynamique, qui est décrite en détail dans liaison dynamique.Its purpose is to allow dynamic binding, which is described in detail in Dynamic binding.

dynamic est considéré comme identique à object , sauf dans les points suivants :dynamic is considered identical to object except in the following respects:

  • Les opérations sur les expressions de type dynamic peuvent être liées dynamiquement (liaison dynamique).Operations on expressions of type dynamic can be dynamically bound (Dynamic binding).
  • L’inférence de type (inférence de type) préfère dynamic object si les deux sont des candidats.Type inference (Type inference) will prefer dynamic over object if both are candidates.

En raison de cette équivalence, les éléments suivants sont les suivants :Because of this equivalence, the following holds:

  • Il existe une conversion d’identité implicite entre object et dynamic , et entre les types construits qui sont identiques lors du remplacement dynamic de par objectThere is an implicit identity conversion between object and dynamic, and between constructed types that are the same when replacing dynamic with object
  • Les conversions implicites et explicites vers et à partir de object s’appliquent également à et à partir de dynamic .Implicit and explicit conversions to and from object also apply to and from dynamic.
  • Les signatures de méthode qui sont les mêmes lors du remplacement dynamic de par object sont considérées comme la même signatureMethod signatures that are the same when replacing dynamic with object are considered the same signature
  • Le type dynamic ne peut pas être distingué de object au moment de l’exécution.The type dynamic is indistinguishable from object at run-time.
  • Une expression du type dynamic est appelée expression dynamique.An expression of the type dynamic is referred to as a dynamic expression.

Type de chaîneThe string type

Le string type est un type de classe sealed qui hérite directement de object .The string type is a sealed class type that inherits directly from object. Les instances de la string classe représentent des chaînes de caractères Unicode.Instances of the string class represent Unicode character strings.

Les valeurs du string type peuvent être écrites sous la forme de littéraux de chaîne (littéraux de chaîne).Values of the string type can be written as string literals (String literals).

Le mot clé string est simplement un alias pour la classe prédéfinie System.String .The keyword string is simply an alias for the predefined class System.String.

Types interfaceInterface types

Une interface définit un contrat.An interface defines a contract. Une classe ou un struct qui implémente une interface doit adhérer à son contrat.A class or struct that implements an interface must adhere to its contract. Une interface peut hériter de plusieurs interfaces de base, et une classe ou un struct peut implémenter plusieurs interfaces.An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces.

Les types d’interface sont décrits dans interfaces.Interface types are described in Interfaces.

Types de tableauxArray types

Un tableau est une structure de données qui contient zéro, une ou plusieurs variables accessibles par le biais d’index calculés.An array is a data structure that contains zero or more variables which are accessed through computed indices. Les variables contenues dans un tableau, également appelé éléments du tableau, sont tous du même type, et ce type est appelé type d’élément du tableau.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.

Les types tableau sont décrits dans les tableaux.Array types are described in Arrays.

Types déléguésDelegate types

Un délégué est une structure de données qui fait référence à une ou plusieurs méthodes.A delegate is a data structure that refers to one or more methods. Pour les méthodes d’instance, elle fait également référence aux instances d’objet correspondantes.For instance methods, it also refers to their corresponding object instances.

L’équivalent le plus proche d’un délégué en C ou C++ est un pointeur de fonction, mais alors qu’un pointeur de fonction ne peut faire référence qu’à des fonctions statiques, un délégué peut faire référence à la fois à des méthodes statiques et d’instance.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. Dans ce dernier cas, le délégué stocke non seulement une référence au point d’entrée de la méthode, mais également une référence à l’instance d’objet sur laquelle appeler la méthode.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.

Les types délégués sont décrits dans délégués.Delegate types are described in Delegates.

Boxing et unboxingBoxing and unboxing

Le concept de boxing et d’unboxing est central pour le système de type de C#.The concept of boxing and unboxing is central to C#'s type system. Il fournit un pont entre Value_type s et reference_type s en autorisant la conversion d’une valeur d’un Value_type en type et inversement 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. Le boxing et l’unboxing permettent une vue unifiée du système de type dans lequel une valeur de n’importe quel type peut finalement être traitée comme un objet.Boxing and unboxing enables a unified view of the type system wherein a value of any type can ultimately be treated as an object.

Conversions boxingBoxing conversions

Une conversion boxing permet à un Value_type d’être implicitement converti en reference_type.A boxing conversion permits a value_type to be implicitly converted to a reference_type. Les conversions boxing suivantes existent :The following boxing conversions exist:

  • Depuis n’importe quel Value_type vers le type object .From any value_type to the type object.
  • Depuis n’importe quel Value_type vers le type System.ValueType .From any value_type to the type System.ValueType.
  • De tout non_nullable_value_type à n’importe quel INTERFACE_TYPE implémenté par le Value_type.From any non_nullable_value_type to any interface_type implemented by the value_type.
  • De tout nullable_type à n’importe quel INTERFACE_TYPE implémenté par le type sous-jacent de l' nullable_type.From any nullable_type to any interface_type implemented by the underlying type of the nullable_type.
  • Depuis n’importe quel enum_type vers le type System.Enum .From any enum_type to the type System.Enum.
  • À partir de tout nullable_type avec un enum_type sous-jacent au type System.Enum .From any nullable_type with an underlying enum_type to the type System.Enum.
  • Notez qu’une conversion implicite à partir d’un paramètre de type sera exécutée comme conversion boxing si, au moment de l’exécution, elle finit par convertir un type valeur en un type référence (conversions implicites impliquant des paramètres de type).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).

Le boxing d’une valeur d’une non_nullable_value_type consiste à allouer une instance d’objet et à copier la valeur non_nullable_value_type dans cette instance.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.

Le boxing d’une valeur d’une nullable_type produit une référence null s’il s’agit de la null valeur (a la valeur HasValue false ), ou le résultat de la désencapsulation et du boxing de la valeur sous-jacente dans le cas contraire.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.

Le processus réel de boxing d’une valeur d’une non_nullable_value_type est expliqué plus particulièrement en imaginant l’existence d’une classe Boxing générique, qui se comporte comme si elle avait été déclarée comme suit :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;
    }
}

Le boxing d’une valeur v de type T se compose maintenant de l’exécution de l’expression new Box<T>(v) et du retour de l’instance résultante sous la forme d’une valeur de type 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. Ainsi, les instructionsThus, the statements

int i = 123;
object box = i;

correspondent de manière conceptuelle àconceptually correspond to

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

Une classe de boxing comme Box<T> ci-dessus n’existe pas réellement et le type dynamique d’une valeur boxed n’est pas en fait un type 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. Au lieu de cela, une valeur boxed de type T a le type dynamique T , et une vérification de type dynamique à l’aide de l' is opérateur peut simplement référencer le type 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. Par exemple,For example,

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

génère la chaîne « Box contains an int » sur la console.will output the string "Box contains an int" on the console.

Une conversion boxing implique de faire une copie de la valeur convertie.A boxing conversion implies making a copy of the value being boxed. Cela est différent d’une conversion d’un reference_type en type object , dans lequel la valeur continue à faire référence à la même instance et est simplement considérée comme le type le moins dérivé 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. Par exemple, étant donné la déclarationFor example, given the declaration

struct Point
{
    public int x, y;

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

les instructions suivantesthe following statements

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

génère la valeur 10 dans la console, car l’opération boxing implicite qui se produit dans l’assignation de p à box entraîne la copie de la valeur 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. A Point été déclaré class à la place, la valeur 20 est sortie, car p et box référencent la même instance.Had Point been declared a class instead, the value 20 would be output because p and box would reference the same instance.

Conversions unboxingUnboxing conversions

Une conversion unboxing permet à un reference_type d’être converti explicitement en Value_type.An unboxing conversion permits a reference_type to be explicitly converted to a value_type. Les conversions unboxing suivantes existent :The following unboxing conversions exist:

  • Du type object à n’importe quel Value_type.From the type object to any value_type.
  • Du type System.ValueType à n’importe quel Value_type.From the type System.ValueType to any value_type.
  • De tout INTERFACE_TYPE à n’importe quel non_nullable_value_type qui implémente le INTERFACE_TYPE.From any interface_type to any non_nullable_value_type that implements the interface_type.
  • De tout INTERFACE_TYPE à n’importe quel nullable_type dont le type sous-jacent implémente le INTERFACE_TYPE.From any interface_type to any nullable_type whose underlying type implements the interface_type.
  • Du type System.Enum à n’importe quel enum_type.From the type System.Enum to any enum_type.
  • Du type System.Enum à n’importe quel nullable_type avec un enum_type sous-jacent.From the type System.Enum to any nullable_type with an underlying enum_type.
  • Notez qu’une conversion explicite en paramètre de type sera exécutée comme conversion unboxing si, au moment de l’exécution, elle finit par convertir un type référence en un type valeur (conversions dynamiques explicites).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).

Une opération d’unboxing sur un non_nullable_value_type consiste à vérifier en premier lieu que l’instance d’objet est une valeur boxed du non_nullable_value_type donné, puis à copier la valeur hors de l’instance.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 conversion unboxing en nullable_type produit la valeur null du nullable_type si l’opérande source est null ou le résultat encapsulé de la conversion unboxing de l’instance d’objet vers le type sous-jacent de la nullable_type dans le cas contraire.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.

En faisant référence à la classe de boxing imaginaire décrite dans la section précédente, une conversion unboxing d’un objet box en Value_type T consiste à exécuter l’expression ((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. Ainsi, les instructionsThus, the statements

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

correspondent de manière conceptuelle àconceptually correspond to

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

Pour qu’une conversion unboxing vers un non_nullable_value_type donné aboutisse au moment de l’exécution, la valeur de l’opérande source doit être une référence à une valeur boxed de ce 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 l’opérande source est null , une System.NullReferenceException exception est levée.If the source operand is null, a System.NullReferenceException is thrown. Si l’opérande source est une référence à un objet incompatible, une System.InvalidCastException exception est levée.If the source operand is a reference to an incompatible object, a System.InvalidCastException is thrown.

Pour qu’une conversion unboxing vers un nullable_type donné aboutisse au moment de l’exécution, la valeur de l’opérande source doit être null ou une référence à une valeur boxed du non_nullable_value_type sous-jacent de l' 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 l’opérande source est une référence à un objet incompatible, une System.InvalidCastException exception est levée.If the source operand is a reference to an incompatible object, a System.InvalidCastException is thrown.

Types construitsConstructed types

Une déclaration de type générique, par elle-même, dénote un *type générique non lié, qui est utilisé comme « Blueprint » pour former de nombreux types différents, en appliquant des arguments de type.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*_. Les arguments de type sont écrits entre crochets pointus ( < et > ) juste après le nom du type générique.The type arguments are written within angle brackets (< and >) immediately following the name of the generic type. Un type qui comprend au moins un argument de type est appelé type construit.A type that includes at least one type argument is called a constructed type. Un type construit peut être utilisé à la plupart des emplacements dans le langage dans lequel un nom de type peut apparaître.A constructed type can be used in most places in the language in which a type name can appear. Un type générique indépendant peut uniquement être utilisé dans un _typeof_expression * (opérateur typeof).An unbound generic type can only be used within a _typeof_expression* (The typeof operator).

Les types construits peuvent également être utilisés dans les expressions en tant que noms simples (noms simples) ou lors de l’accès à un membre (accès aux membres).Constructed types can also be used in expressions as simple names (Simple names) or when accessing a member (Member access).

Lorsqu’un namespace_or_type_name est évalué, seuls les types génériques avec le nombre correct de paramètres de type sont pris en compte.When a namespace_or_type_name is evaluated, only generic types with the correct number of type parameters are considered. Par conséquent, il est possible d’utiliser le même identificateur pour identifier les différents types, à condition que les types aient des nombres de paramètres de type différents.Thus, it is possible to use the same identifier to identify different types, as long as the types have different numbers of type parameters. Cela est utile pour mélanger des classes génériques et non génériques dans le même programme :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 peut identifier un type construit bien qu’il ne spécifie pas directement les paramètres de type.A type_name might identify a constructed type even though it doesn't specify type parameters directly. Cela peut se produire lorsqu’un type est imbriqué dans une déclaration de classe générique et que le type d’instance de la déclaration conteneur est implicitement utilisé pour la recherche de nom (types imbriqués dans les classes génériques) :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
}

Dans du code unsafe, un type construit ne peut pas être utilisé en tant que unmanaged_type (types pointeur).In unsafe code, a constructed type cannot be used as an unmanaged_type (Pointer types).

Arguments de typeType arguments

Chaque argument dans une liste d’arguments de type est simplement un type.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
    ;

Dans du code non sécurisé (code non sécurisé), un type_argument ne peut pas être un type pointeur.In unsafe code (Unsafe code), a type_argument may not be a pointer type. Chaque argument de type doit satisfaire toutes les contraintes sur le paramètre de type correspondant (contraintes de paramètre de type).Each type argument must satisfy any constraints on the corresponding type parameter (Type parameter constraints).

Types ouverts et fermésOpen and closed types

Tous les types peuvent être classés en tant que * types ouverts _ ou _ types fermés *.All types can be classified as either open types _ or _closed types**. Un type ouvert est un type qui implique des paramètres de type.An open type is a type that involves type parameters. Plus précisément :More specifically:

  • Un paramètre de type définit un type ouvert.A type parameter defines an open type.
  • Un type tableau est un type ouvert si et uniquement si son type d’élément est un type ouvert.An array type is an open type if and only if its element type is an open type.
  • Un type construit est un type ouvert si et seulement si un ou plusieurs de ses arguments de type est un type ouvert.A constructed type is an open type if and only if one or more of its type arguments is an open type. Un type imbriqué construit est un type ouvert si et seulement si un ou plusieurs de ses arguments de type ou les arguments de type de ses types conteneur sont un type ouvert.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 type fermé est un type qui n’est pas un type ouvert.A closed type is a type that is not an open type.

Au moment de l’exécution, tout le code au sein d’une déclaration de type générique est exécuté dans le contexte d’un type construit fermé qui a été créé en appliquant des arguments de type à la déclaration générique.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. Chaque paramètre de type dans le type générique est lié à un type au moment de l’exécution particulier.Each type parameter within the generic type is bound to a particular run-time type. Le traitement au moment de l’exécution de toutes les instructions et expressions se produit toujours avec les types fermés, et les types ouverts se produisent uniquement pendant le traitement au moment de la compilation.The run-time processing of all statements and expressions always occurs with closed types, and open types occur only during compile-time processing.

Chaque type construit fermé a son propre ensemble de variables statiques, qui ne sont pas partagées avec d’autres types construits fermés.Each closed constructed type has its own set of static variables, which are not shared with any other closed constructed types. Étant donné qu’il n’existe pas de type ouvert au moment de l’exécution, aucune variable statique n’est associée à un type ouvert.Since an open type does not exist at run-time, there are no static variables associated with an open type. Deux types construits fermés sont du même type s’ils sont construits à partir du même type générique indépendant, et que leurs arguments de type correspondants sont du même type.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.

Types liés et indépendantsBound and unbound types

Le terme *type indépendant _ fait référence à un type non générique ou à un type générique indépendant.The term *unbound type _ refers to a non-generic type or an unbound generic type. Le terme _ Bound type* fait référence à un type non générique ou à un type construit.The term _ bound type* refers to a non-generic type or a constructed type.

Un type indépendant fait référence à l’entité déclarée par une déclaration de type.An unbound type refers to the entity declared by a type declaration. Un type générique indépendant n’est pas lui-même un type et ne peut pas être utilisé en tant que type d’une variable, d’un argument ou d’une valeur de retour, ou en tant que type de 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 seule construction dans laquelle un type générique indépendant peut être référencé est l' typeof expression (opérateur typeof).The only construct in which an unbound generic type can be referenced is the typeof expression (The typeof operator).

Contraintes de satisfactionSatisfying constraints

Chaque fois qu’un type construit ou une méthode générique est référencé, les arguments de type fournis sont vérifiés par rapport aux contraintes de paramètre de type déclarées sur le type ou la méthode générique (contraintes de paramètre de type).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). Pour chaque where clause, l’argument de type A qui correspond au paramètre de type nommé est vérifié par rapport à chaque contrainte comme suit :For each where clause, the type argument A that corresponds to the named type parameter is checked against each constraint as follows:

  • Si la contrainte est un type de classe, un type d’interface ou un paramètre de type, Let C représente cette contrainte avec les arguments de type fournis, en remplaçant tous les paramètres de type qui apparaissent dans la contrainte.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. Pour satisfaire la contrainte, il faut que le type A soit convertible en type C par l’un des éléments suivants :To satisfy the constraint, it must be the case that type A is convertible to type C by one of the following:
  • Si la contrainte est la contrainte de type référence ( class ), le type A doit correspondre à l’un des éléments suivants :If the constraint is the reference type constraint (class), the type A must satisfy one of the following:
    • A est un type d’interface, un type de classe, un type délégué ou un type tableau.A is an interface type, class type, delegate type or array type. Notez que System.ValueType et System.Enum sont des types référence qui satisfont cette contrainte.Note that System.ValueType and System.Enum are reference types that satisfy this constraint.
    • A est un paramètre de type qui est connu comme étant un type référence (contraintes de paramètre de type).A is a type parameter that is known to be a reference type (Type parameter constraints).
  • Si la contrainte est la contrainte de type valeur ( struct ), le type A doit correspondre à l’un des éléments suivants :If the constraint is the value type constraint (struct), the type A must satisfy one of the following:
    • A est un type struct ou un type enum, mais pas un type Nullable.A is a struct type or enum type, but not a nullable type. Notez que System.ValueType et System.Enum sont des types référence qui ne répondent pas à cette contrainte.Note that System.ValueType and System.Enum are reference types that do not satisfy this constraint.
    • A est un paramètre de type ayant la contrainte de type valeur (contraintes de paramètre de type).A is a type parameter having the value type constraint (Type parameter constraints).
  • Si la contrainte est la contrainte de constructeur new() , le type A ne doit pas être abstract et doit avoir un constructeur sans paramètre public.If the constraint is the constructor constraint new(), the type A must not be abstract and must have a public parameterless constructor. Cette condition est remplie si l’une des conditions suivantes est remplie :This is satisfied if one of the following is true:

Une erreur de compilation se produit si une ou plusieurs des contraintes d’un paramètre de type ne sont pas satisfaites par les arguments de type donnés.A compile-time error occurs if one or more of a type parameter's constraints are not satisfied by the given type arguments.

Étant donné que les paramètres de type ne sont pas hérités, les contraintes ne sont jamais héritées non plus.Since type parameters are not inherited, constraints are never inherited either. Dans l’exemple ci-dessous, D doit spécifier la contrainte sur son paramètre de type T afin qu’elle T satisfasse à la contrainte imposée par la classe de 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 revanche, E la classe n’a pas besoin de spécifier de contrainte, car List<T> implémente IEnumerable pour 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>> {...}

Paramètres de typeType parameters

Un paramètre de type est un identificateur désignant un type valeur ou un type référence auquel le paramètre est lié au moment de l’exécution.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
    ;

Étant donné qu’un paramètre de type peut être instancié avec un grand nombre d’arguments de type réels différents, les paramètres de type ont des opérations et des restrictions légèrement différentes de celles des autres types.Since a type parameter can be instantiated with many different actual type arguments, type parameters have slightly different operations and restrictions than other types. notamment :These include:

En tant que type, les paramètres de type sont purement une construction au moment de la compilation.As a type, type parameters are purely a compile-time construct. Au moment de l’exécution, chaque paramètre de type est lié à un type au moment de l’exécution qui a été spécifié en fournissant un argument de type à la déclaration de type générique.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. Ainsi, le type d’une variable déclarée avec un paramètre de type sera, au moment de l’exécution, un type construit fermé (types ouverts et fermés).Thus, the type of a variable declared with a type parameter will, at run-time, be a closed constructed type (Open and closed types). L’exécution de toutes les instructions et expressions impliquant des paramètres de type au moment de l’exécution utilise le type réel fourni comme argument de type pour ce paramètre.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.

Types d’arborescence d’expressionExpression tree types

*Les arborescences d’expressions _ permettent aux expressions lambda d’être représentées en tant que structures de données au lieu du code exécutable.*Expression trees _ permit lambda expressions to be represented as data structures instead of executable code. Les arborescences d’expressions sont des valeurs des types d’arborescence d’expression* de la forme System.Linq.Expressions.Expression<D> , où D est un type délégué.Expression trees are values of _ expression tree types* of the form System.Linq.Expressions.Expression<D>, where D is any delegate type. Pour le reste de cette spécification, nous faisons référence à ces types à l’aide de la syntaxe abrégée Expression<D> .For the remainder of this specification we will refer to these types using the shorthand Expression<D>.

S’il existe une conversion d’une expression lambda en un type délégué D , une conversion existe également dans le type d’arborescence de l’expression 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>. Tandis que la conversion d’une expression lambda en un type délégué génère un délégué qui fait référence à du code exécutable pour l’expression lambda, la conversion en un type d’arborescence d’expression crée une représentation d’arborescence d’expression de l’expression 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.

Les arborescences d’expressions sont des représentations efficaces des données en mémoire des expressions lambda et rendent la structure de l’expression lambda transparente et explicite.Expression trees are efficient in-memory data representations of lambda expressions and make the structure of the lambda expression transparent and explicit.

Tout comme un type délégué D , Expression<D> est dit avoir des types de paramètre et de retour, qui sont identiques à ceux 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.

L’exemple suivant représente une expression lambda à la fois comme du code exécutable et comme une arborescence de l’expression.The following example represents a lambda expression both as executable code and as an expression tree. Étant donné qu’une conversion existe dans Func<int,int> , une conversion existe également pour 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

À la suite de ces assignations, le délégué del référence une méthode qui retourne x + 1 , et l’arborescence de l’expression exp fait référence à une structure de données qui décrit l’expression 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 définition exacte du type générique Expression<D> , ainsi que les règles précises pour la construction d’une arborescence d’expressions quand une expression lambda est convertie en un type d’arborescence d’expression, sont toutes deux en dehors de la portée de cette spécification.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.

Deux choses sont importantes pour rendre explicite :Two things are important to make explicit:

  • Toutes les expressions lambda ne peuvent pas être converties en arborescences d’expressions.Not all lambda expressions can be converted to expression trees. Par exemple, les expressions lambda avec corps d’instruction et les expressions lambda contenant des expressions d’assignation ne peuvent pas être représentées.For instance, lambda expressions with statement bodies, and lambda expressions containing assignment expressions cannot be represented. Dans ce cas, une conversion existe toujours, mais elle échoue au moment de la compilation.In these cases, a conversion still exists, but will fail at compile-time. Ces exceptions sont détaillées dans les conversions de fonctions anonymes.These exceptions are detailed in Anonymous function conversions.

  • Expression<D> offre une méthode d’instance Compile qui produit un délégué de type D :Expression<D> offers an instance method Compile which produces a delegate of type D:

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

    L’appel de ce délégué provoque l’exécution du code représenté par l’arborescence de l’expression.Invoking this delegate causes the code represented by the expression tree to be executed. Par conséquent, étant donné les définitions ci-dessus, del et DEL2 sont équivalentes, et les deux instructions suivantes ont le même effet :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);
    

    Après l’exécution de ce code i1 , i2 la valeur est 2 .After executing this code, i1 and i2 will both have the value 2.