Modificateurs

Références

L'actualité

Librairie

L'information

abstract

Le modificateur abstract indique que l'élément en cours de modification a une implémentation manquante ou incomplète. Le modificateur abstract peut être utilisé avec des classes, des méthodes, des propriétés, des indexeurs et des événements. Dans une déclaration de classe, utilisez le modificateur abstract pour indiquer qu'une classe doit uniquement servir de classe de base pour d'autres classes. Les membres définis comme abstraits, ou inclus dans une classe abstraite, doivent être implémentés par des classes dérivées de la classe abstraite.

Exemple

Dans cet exemple, la classe Square doit fournir une implémentation de Area, car elle dérive de la classe ShapesClass :

--------
Les classes abstraites présentent les caractéristiques suivantes :

  • Une classe abstraite ne peut pas être instanciée.
  • Une classe abstraite peut contenir des méthodes et accesseurs abstraits.
  • Il n'est pas possible de modifier une classe abstraite à l'aide du modificateur sealed, car les deux modificateurs ont des significations opposées. Le modificateur sealed empêche qu'une classe soit héritée et le modificateur abstract exige qu'une classe soit héritée.
  • Une classe non abstraite dérivée d'une classe abstraite doit inclure des implémentations réelles de tous les accesseurs et méthodes abstraits hérités.

Dans une déclaration de méthode ou de propriété, utilisez le modificateur abstract pour indiquer que la méthode ou la propriété ne contient pas d'implémentation.

Les méthodes abstraites présentent les caractéristiques suivantes :

Une méthode abstraite est implicitement une méthode virtuelle.

Les déclarations de méthodes abstraites sont autorisées uniquement dans les classes abstraites.

Comme une déclaration de méthode abstraite ne fournit pas d'implémentation réelle, il n'y a pas de corps de méthode ; la déclaration de méthode se termine simplement par un point-virgule, et la signature n'est pas suivie d'accolades ({ }). Par exemple :

-------

L'implémentation est fournie par une méthode override, qui est membre d'une classe non abstraite.

L'utilisation des modificateurs static ou virtual dans une déclaration de méthode abstraite serait une erreur.

Les propriétés abstraites se comportent comme les méthodes abstraites, à l'exception des différences dans la syntaxe de déclaration et d'appel.

L'utilisation du modificateur abstract sur une propriété statique serait une erreur.

Une propriété abstraite héritée peut être substituée dans une classe dérivée en incluant une déclaration de propriété qui utilise le modificateur override.

Pour plus d'informations sur les classes abstraites, consultez Classes abstract et sealed et membres de classe.

Une classe abstraite doit fournir une implémentation pour tous les membres d'interface.

Une classe abstraite qui implémente une interface peut mapper les méthodes d'interface à des méthodes abstraites. Par exemple :

----------


Exemple

Dans cet exemple, la classe DerivedClass est dérivée de la classe abstraite BaseClass. La classe abstraite contient une méthode abstraite, AbstractMethod, et deux propriétés abstraites, X et Y.

-------

Dans l'exemple précédent, si vous tentez d'instancier la classe abstraite en utilisant une instruction comme celle-ci :

-------

Vous obtenez une erreur indiquant que le compilateur ne peut pas créer une instance de la classe abstraite BaseClass.


async

Utilisez le modificateur async pour spécifier qu'une méthode, une expression lambda ou une méthode anonyme sont asynchrones. Si vous utilisez ce modificateur sur une méthode ou une expression, il s'agit d'une méthode async. L'exemple suivant définit une méthode async nommée ExampleMethodAsync :

--------

Si vous débutez en programmation asynchrone ou que vous ne comprenez pas comment une méthode async utilise le mot clé await pour un travail potentiellement long sans bloquer le thread de l'appelant, lisez l'introduction dans Programmation asynchrone avec async et await. Le code suivant se trouve dans une méthode async et appelle la méthode HttpClient.GetStringAsync :

---------

Une méthode async s'exécute de façon synchrone jusqu'à ce qu'elle atteigne sa première expression await, où elle est suspendue jusqu'à ce que la tâche attendue soit terminée. Dans le même temps, le contrôle retourne à l'appelant de la méthode, comme le montre l'exemple indiqué dans la section suivante.

Si la méthode que le mot clé async modifie ne contient pas une expression ou une instruction await, la méthode s'exécute de façon synchrone. Un avertissement du compilateur vous signale toutes les méthodes async qui ne contiennent pas d'instructions await, car cette situation peut indiquer une erreur. Consultez Avertissement du compilateur (niveau 1) CS4014.

Le mot clé async est contextuel, car il est un mot clé uniquement lorsqu'il modifie une méthode, une expression lambda ou une méthode anonyme. Dans tous les autres contextes, il est interprété comme un identificateur.

Exemple

L'exemple suivant montre la structure et le flux de contrôle entre un gestionnaire d'événements asynchrones, StartButton_Click, et une méthode async, ExampleMethodAsync. Le résultat de la méthode async est le nombre de caractères d'une page web. Le code convient pour une application WPF (Windows Presentation Foundation) ou une application du Windows Store que vous créez dans Visual Studio ; consultez les commentaires du code pour configurer l'application.

Vous pouvez exécuter ce code dans Visual Studio en tant qu'application Windows Presentation Foundation (WPF) ou qu'application du Windows Store. Vous avez besoin d'un contrôle Button nommé StartButton et d'un contrôle Textbox nommé ResultsTextBox. N'oubliez pas de définir les noms et le gestionnaire afin d'obtenir un résultat semblable à ceci :

--------

Pour exécuter le code en tant qu'application WPF :

  • Collez ce code dans la classe MainWindow dans MainWindow.xaml.cs.
  • Ajoutez une référence à System.Net.Http.
  • Ajoutez une directive using à System.Net.Http.
      • Pour exécuter le code comme une application du Windows Store :
      • Collez ce code dans la classe MainPage dans MainPage.xaml.cs.
      • Ajouter des directives using pour System.Net.Http et System.Threading.Tasks.


      ---------


      Types de retours

      Une méthode async peut avoir les types de retour suivants :

      • Task
      • Task
      • void, qui doit être utilisé uniquement pour les gestionnaires d'événements.
      • à compter de C# 7.0, tout type ayant une méthode GetAwaiter accessible. Le type System.Threading.Tasks.ValueTask est une implémentation de ce genre. Il est disponible en ajoutant le package NuGet System.Threading.Tasks.Extensions.

      La méthode async ne peut déclarer aucun paramètre in, ref ou out, ni avoir une valeur de retour de référence, mais elle peut appeler des méthodes qui ont ces paramètres.

      Vous spécifiez Task comme type de retour d'une méthode async si l'instruction return de la méthode spécifie un opérande de type TResult. Utilisez Task si aucune valeur significative n'est retournée lorsque la méthode est terminée. En d'autres termes, un appel à la méthode retourne Task, mais lorsque Task est terminé, toute expression await qui attend Task prend la valeur void.

      Vous utilisez le type de retour void principalement pour définir les gestionnaires d'événements, qui ont besoin de ce type de retour. L'appelant d'une méthode async retournant void ne peut pas l'attendre et ne peut pas intercepter les exceptions levées par la méthode.

      à partir de C# 7.0, vous retournez un autre type, en général un type valeur, qui a une méthode GetAwaiter permettant de limiter les allocations de mémoire dans les sections de code critiques pour les performances.

const

Vous utilisez le mot clé const pour déclarer un champ constant ou un élément local constant. Les champs et les éléments locaux constants ne sont pas des variables et ne peuvent pas être modifiés. Les constantes peuvent être des chiffres, des valeurs booléennes, des chaînes ou une référence null. Ne créez pas une constante pour représenter des informations qui doivent être modifiées. Par exemple, n'utilisez pas un champ constant pour stocker le prix d'un service, le numéro de version du produit ou le nom de la marque d'une société. Ces valeurs peuvent changer dans le temps, et dans la mesure où les compilateurs propagent les constantes, le code compilé avec vos bibliothèques devra être recompilé pour refléter ces modifications. Consultez également le mot clé readonly. Par exemple :

--------


Notes

Le type d'une déclaration constante indique le type des membres introduit par la déclaration. L'initialiseur d'un élément local constant ou d'un champ constant doit être une expression constante qui peut être implicitement convertie en type cible.

Une expression constante est une expression qui peut être complètement évaluée au moment de la compilation. C'est pourquoi, les seules valeurs possibles pour les constantes des types référence sont string et une référence null.

La déclaration constante peut déclarer plusieurs constantes, notamment :

-------

Le modificateur static n'est pas autorisé dans une déclaration constante.

Une constante peut être utilisée dans une expression constante, comme suit :

---------


Le mot clé readonly est différent du mot clé const. Un champ const ne peut être initialisé qu'au moment de la déclaration du champ. Un champ readonly peut être initialisé dans la déclaration ou dans un constructeur. C'est pourquoi, les champs readonly peuvent avoir des valeurs différentes en fonction du constructeur utilisé. De même, bien qu'un champ const soit une constante au moment de la compilation, le champ readonly peut être utilisé pour des constantes au moment de l'exécution, comme ci-après : public static readonly uint l1 = (uint)DateTime.Now.Ticks;


Exemple


-----------


Exemple

Cet exemple montre comment utiliser des constantes en tant que variables locales.

--------


event

Le mot clé event sert à déclarer un événement dans une classe d'éditeur.

Exemple

L'exemple suivant montre comment déclarer et déclencher un événement qui utilise EventHandler comme type délégué sous-jacent. Pour obtenir l'exemple de code complet qui illustre aussi comment utiliser le type délégué générique EventHandler et comment s'abonner à un événement et créer une méthode de gestionnaire d'événements, consultez Guide pratique pour publier des événements conformes aux indications du .NET Framework.

-------

Les événements constituent un type spécial de délégué multicast qui peut uniquement être appelé au sein de la classe ou du struct où ils sont déclarés (la classe d'éditeur). Si d'autres classes ou structs s'abonnent à l'événement, leurs méthodes de gestionnaire d'événements sont appelées quand la classe d'éditeur déclenche l'événement. Pour plus d'informations et pour obtenir des exemples de code, consultez événements et Délégués.

Les événements peuvent être marqués comme public, private, protected, internal, protected internal ou private protected. Ces modificateurs d'accès définissent comment les utilisateurs de la classe peuvent accéder à l'événement. Pour plus d'informations, consultez la page Modificateurs d'accès.

--- tbl

Un événement peut être déclaré comme événement statique à l'aide du mot clé static. Cela rend le champ accessible à tout moment aux appelants, même s'il n'existe aucune instance de la classe. Pour plus d'informations, consultez Classes statiques et membres de classe statique.

Un événement peut être marqué comme événement virtuel à l'aide du mot clé virtual. Cela permet aux classes dérivées de substituer le comportement d'événement à l'aide du mot clé override. Pour plus d'informations, consultez Héritage. Un événement qui se substitue à un événement virtuel peut également être sealed, ce qui signifie que pour les classes dérivées il n'est plus virtuel. Pour finir, un événement peut être déclaré abstract, ce qui signifie que le compilateur ne génère pas les blocs d'accesseurs d'événement add et remove. Ainsi, les classes dérivées doivent fournir leur propre implémentation.


extern

Le modificateur extern permet de déclarer une méthode qui est implémentée en externe. Le modificateur extern est souvent utilisé avec l'attribut DllImport lors de l'utilisation de services Interop à appeler dans du code non managé. Dans ce cas, la méthode doit également être déclarée comme static, comme indiqué dans l'exemple suivant :

-------

Le mot clé extern peut également définir un alias d'assembly externe, permettant ainsi de référencer différentes versions du même composant à partir d'un seul assembly. Pour plus d'informations, consultez extern alias.

C'est une erreur d'utiliser conjointement les modificateurs abstract et extern pour modifier le même membre. L'utilisation du modificateur extern signifie que la méthode est implémentée en dehors du code C#, tandis que l'utilisation du modificateur abstract signifie que l'implémentation de la méthode n'est pas effectuée dans la classe.

L'utilisation du mot clé extern est plus restreinte dans C# que dans C++. Pour comparer son utilisation dans C# et C++, consultez : Utilisation d'extern pour spécifier la liaison dans le Guide de référence du langage C++.


Exemple

Dans cet exemple, le programme reçoit une chaîne provenant de l'utilisateur et l'affiche dans une boîte de message. Le programme utilise la méthode MessageBox importée de la bibliothèque User32.dll.

--------


Exemple

Cet exemple illustre un programme C# qui fait appel à une bibliothèque C (une DLL native).

Créez le fichier C suivant et nommez-le cmdll.c :

---------

Ouvrez une fenêtre d'invite de commandes d'outils natifs Visual Studio x64 (ou x32) à partir du répertoire d'installation de Visual Studio et compilez le fichier cmdll.c en tapant cl -LD cmdll.c à l'invite de commandes.

Dans le même répertoire, créez le fichier C# suivant et nommez-le cm.cs :

----------

Ouvrez une fenêtre d'invite de commandes d'outils natifs Visual Studio x64 (ou x32) à partir du répertoire d'installation de Visual Studio et compilez le fichier cm.cs en tapant :

Cette opération crée le fichier exécutable cm.exe.

Exécutez cm.exe. La méthode SampleMethod passe la valeur 5 au fichier DLL, qui retourne la valeur multipliée par 10. Le programme génère la sortie suivante :

-------


in

Pour les paramètres de type générique, le mot clé in spécifie que le paramètre de type est contravariant. Vous pouvez utiliser le mot clé in dans les interfaces et délégués génériques.

La contravariance permet d'utiliser un type moins dérivé que celui spécifié par le paramètre générique. Cela permet la conversion implicite des classes qui implémentent des interfaces contravariantes, ainsi que la conversion implicite des types délégués. La covariance et la contravariance des paramètres de type générique sont prises en charge pour les types référence, mais pas pour les types valeur.

Un type peut être déclaré comme étant contravariant dans une interface ou un délégué générique uniquement s'il définit le type des paramètres d'une méthode et non le type de retour d'une méthode. Les paramètres In, ref et out doivent être invariants, ce qui signifie qu'ils sont ni covariants ni contravariants.

Une interface qui possède un paramètre de type contravariant permet à ses méthodes d'accepter des arguments de types moins dérivés que ceux spécifiés par le paramètre de type d'interface. Par exemple, dans l'interface IComparer, le type T est contravariant, vous pouvez attribuer un objet du type IComparer à un objet du type IComparer sans utiliser de méthode de conversion spéciale si Employee hérite Person.

Un délégué contravariant peut être assigné à un autre délégué du même type, mais avec un paramètre de type générique moins dérivé.

Interface générique contravariante

L'exemple suivant montre comment déclarer, étendre et implémenter une interface générique contravariante. Il montre également comment utiliser la conversion implicite pour les classes qui implémentent cette interface.

----------


Délégué générique contravariant

L'exemple de code suivant montre comment déclarer, instancier et invoquer un délégué générique contravariant. Il montre également comment convertir implicitement un type délégué.

-------


out

Pour les paramètres de type générique, le mot clé out spécifie que le paramètre de type est covariant. Vous pouvez utiliser le mot clé out dans les interfaces et délégués génériques.

La covariance permet d'utiliser un type plus dérivé que celui spécifié par le paramètre générique. Cela permet la conversion implicite des classes qui implémentent des interfaces covariantes, ainsi que la conversion implicite des types délégués. La covariance et la contravariance sont prises en charge pour les types référence, mais pas pour les types valeur.

Une interface qui possède un paramètre de type covariant permet à ses méthodes de retourner des types plus dérivés que ceux spécifiés par le paramètre de type. Par exemple, comme dans le .NET Framework 4, dans IEnumerable, le type T est covariant, vous pouvez assigner un objet du type IEnumerable(Of String) à un objet du type IEnumerable(Of Object) sans utiliser de méthode de conversion spéciale.

Un délégué covariant peut être assigné à un autre délégué du même type, mais avec un paramètre de type générique plus dérivé.

Exemple - interface générique covariante

L'exemple suivant montre comment déclarer, étendre et implémenter une interface générique covariante. Il montre également comment utiliser la conversion implicite pour les classes qui implémentent une interface covariante.

--------

Dans une interface générique, un paramètre de type peut être déclaré covariant s'il satisfait aux conditions suivantes :

Le paramètre de type est utilisé uniquement comme type de retour des méthodes d'interface, mais pas comme type des arguments de méthode.

Il existe une exception à cette règle. Si une interface covariante a un délégué générique contravariant comme paramètre de méthode, vous pouvez utiliser le type covariant comme paramètre de type générique pour ce délégué. Pour plus d'informations sur les délégués génériques covariants et contravariants, consultez Variance dans les délégués et Utilisation de la variance pour les délégués génériques Func et Action.

Le paramètre de type n'est pas utilisé comme contrainte générique pour les méthodes d'interface.

Exemple - délégué générique covariant

L'exemple de code suivant montre comment déclarer, instancier et appeler un délégué générique covariant. Il montre également comment convertir implicitement des types délégués.

----------

Dans un délégué générique, un type peut être déclaré comme étant covariant s'il est utilisé uniquement comme type de retour des méthodes, mais pas pour des arguments de méthode.

override

Le modificateur override est nécessaire pour étendre ou modifier l'implémentation abstraite ou virtuelle d'une méthode, d'une propriété, d'un indexeur ou d'un événement hérités.

Exemple

Dans cet exemple, la classe Square doit fournir une implémentation substituée de Area, car Area est héritée de la classe abstraite ShapesClass :

--------

Une méthode override fournit une nouvelle implémentation d'un membre hérité d'une classe de base. La méthode substituée par une déclaration override est appelée méthode de base substituée. La méthode de base substituée doit avoir la même signature que la méthode override. Pour plus d'informations sur l'héritage, consultez Héritage.

Vous ne pouvez pas surcharger une méthode statique ou non virtuelle. La méthode de base substituée doit être virtual, abstract ou override.

Une déclaration override ne peut pas changer l'accessibilité de la méthode virtual. Les deux méthodes override et virtual doivent avoir le même modificateur de niveau d'accès.

Vous ne pouvez pas utiliser les modificateurs new, static ou virtual pour modifier une méthode override.

Une déclaration de propriété de substitution doit spécifier exactement les mêmes modificateur d'accès, type et nom que la propriété héritée, et la propriété substituée doit être virtual, abstract ou override.

Exemple

Cet exemple définit une classe de base nommée Employee et une classe dérivée nommée SalesEmployee. La classe SalesEmployee inclut un champ supplémentaire (salesbonus) et substitue la méthode CalculatePay afin de la prendre en compte.

-------


readonly

Le mot clé readonly est un modificateur qui peut être utilisé dans trois contextes :
  • Dans une déclaration de champ, readonly indique qu'une affectation à destination d'un champ peut survenir uniquement dans le cadre de la déclaration ou dans un constructeur de la même classe.
  • Dans une définition readonly struct, readonly indique que le struct est immuable.
  • Dans un ref readonlyretour de la méthode, le modificateur readonly indique que la méthode retourne une référence et que les écritures ne sont pas autorisés pour cette référence.
Les deux contextes finaux ont été ajoutés dans C# 7.2.

Exemple de champ en lecture seule

Dans cet exemple, la valeur du champ year ne peut pas être modifiée dans la méthode ChangeYear, même si une valeur lui est affectée dans le constructeur de classe :

---------

Vous pouvez affecter une valeur à un champ readonly uniquement dans les contextes suivants :

Lorsque la variable est initialisée dans la déclaration, par exemple :

-------

Dans un constructeur d'instance de la classe qui contient la déclaration de champ d'instance.

Dans le constructeur statique de la classe qui contient la déclaration de champ statique.

Ces contextes de constructeur sont aussi les seuls contextes dans lesquels il est possible de passer un champ readonly comme paramètre out ou ref.

Le mot clé readonly est différent du mot clé const. Un champ const ne peut être initialisé qu'au moment de la déclaration du champ. Un champ readonly peut être assigné plusieurs fois dans la déclaration de champ et dans un constructeur. C'est pourquoi, les champs readonly peuvent avoir des valeurs différentes en fonction du constructeur utilisé. De même, alors qu'un champ const est une constante au moment de la compilation, le champ readonly peut être utilisé pour des constantes au moment de l'exécution, comme dans l'exemple suivant :


--------


---------

Dans l'exemple précédent, si vous utilisez une instruction telle que dans l'exemple suivant :

p2.y = 66; // Error

vous obtenez le message d'erreur du compilateur :

A readonly field cannot be assigned to (except in a constructor or a variable initializer)

Exemple de struct readonly

Le modificateur readonly dans une définition struct déclare que le struct est immuable. Chaque champ d'instance du struct doit être marqué readonly, comme dans l'exemple suivant :

--------

L'exemple précédent utilise les propriétés automatiques readonly pour déclarer son stockage. Il donne l'instruction au compilateur de créer des champs de stockage readonly pour ces propriétés. Vous pouvez aussi déclarer des champs readonly directement :

--------

L'ajout d'un champ non marqué readonly génère l'erreur du compilateur CS8340 : "Les champs d'instance de structs en lecture seule doivent être en lecture seule."

Exemple de retour ref readonly

Le modificateur readonly au niveau d'un ref return indique que la référence retournée ne peut pas être modifiée. L'exemple suivant retourne une référence à l'origine. Il utilise le modificateur readonly pour indiquer que les appelants ne peuvent pas modifier l'origine :

--------

Le type retourné ne doit pas nécessairement être un readonly struct. Tout type pouvant être retourné par ref peut être retourné par ref readonly.

sealed

Lorsqu'il est appliqué à une classe, le modificateur sealed empêche les autres classes d'en hériter. Dans l'exemple suivant, la classe B hérite de la classe A, mais aucune classe ne peut hériter de la classe B.

--------

Vous pouvez également utiliser le modificateur sealed sur une méthode ou une propriété qui substitue une méthode ou une propriété virtuelle dans une classe de base. Ainsi, vous pouvez autoriser les classes à dériver de votre classe et les empêcher de substituer des méthodes ou des propriétés virtuelles spécifiques.

Exemple

Dans l'exemple suivant, Z hérite de Y mais Z ne peut pas substituer la fonction virtuelle F qui est déclarée dans X et scellée (sealed) dans Y.

---------

Lorsque vous définissez de nouvelles méthodes ou propriétés dans une classe, vous pouvez empêcher les classes dérivées de les substituer en ne les déclarant pas comme virtuelles.

Une erreur consiste à utiliser le modificateur abstract avec une classe sealed, car une classe abstraite doit être héritée par une classe qui fournit une implémentation des méthodes ou des propriétés abstraites.

Lorsqu'il est appliqué à une méthode ou une propriété, le modificateur sealed doit toujours être utilisé avec override.

Comme les structs sont implicitement sealed, ils ne peuvent pas être hérités.

Exemple


---------

Dans l'exemple précédent, vous pouvez essayer d'hériter de la classe sealed à l'aide de l'instruction suivante :

class MyDerivedC: SealedClass {} // Error

Le résultat est un message d'erreur :

'MyDerivedC': cannot derive from sealed type 'SealedClass'


static

Utilisez le modificateur static pour déclarer un membre statique, qui appartient au type lui-même plutôt qu'à un objet spécifique. Le modificateur static peut être utilisé avec des classes, des champs, des méthodes, des propriétés, des opérateurs, des événements et des constructeurs. En revanche, il ne peut pas être utilisé avec des indexeurs, des finaliseurs ni des types autres que des classes. Pour plus d'informations, consultez Classes statiques et membres de classe statique.

Exemple

La classe suivante est déclarée comme static et contient uniquement des méthodes static :

-------

Une déclaration de constante ou de type est implicitement un membre statique.

Un membre statique ne peut pas être référencé via une instance. Au lieu de cela, il est référencé via le nom de type. Par exemple, considérons la classe suivante :

--------

Pour faire référence au membre statique x, utilisez le nom complet MyBaseC.MyStruct.x, à moins que le membre soit accessible à partir de la même portée :

------

Alors qu'une instance d'une classe contient une copie distincte de tous les champs d'instance de la classe, il existe une seule copie de chaque champ statique.

Il n'est pas possible d'utiliser this pour référencer des méthodes statiques ou des accesseurs de propriété.

Si le mot clé static est appliqué à une classe, tous les membres de la classe doivent être statiques.

Les classes et les classes statiques peuvent avoir des constructeurs statiques. Les constructeurs statiques sont appelés à un moment donné entre le démarrage du programme et l'instanciation de la classe.

L'utilisation du mot clé static est plus restreinte que dans C++. Pour comparer avec le mot clé C++, consultez Classes de stockage (C++).

Pour illustrer les membres statiques, considérons une classe qui représente un employé d'une entreprise. Supposons que la classe contient une méthode pour compter les employés et un champ pour stocker le nombre d'employés. La méthode et le champ n'appartiennent à aucune instance d'employé. Au lieu de cela, ils appartiennent à la classe entreprise. Par conséquent, ils doivent être déclarés comme membres statiques de cette classe.

Exemple

Cet exemple lit le nom et l'ID d'un nouvel employé, incrémente d'une unité le compteur d'employés et affiche les informations concernant le nouvel employé et le nouveau nombre d'employés. Pour plus de simplicité, ce programme lit le nombre actuel d'employés à partir du clavier. Dans une application réelle, ces informations doivent être lues à partir d'un fichier.

---------


Exemple

Cet exemple montre que bien que vous puissiez initialiser un champ statique à l'aide d'un autre champ statique encore non déclaré, les résultats sont indéfinis tant que vous n'assignez pas explicitement une valeur au champ statique.

--------


unsafe

Le mot clé unsafe désigne un contexte non sécurisé, qui est requis pour toute opération impliquant des pointeurs. Pour plus d'informations, consultez l'article Pointeurs et code unsafe.

Vous pouvez utiliser le modificateur unsafe dans la déclaration d'un type ou d'un membre. Toute l'étendue de texte du type ou du membre est ainsi considérée comme un contexte unsafe. Par exemple, ce qui suit est une méthode déclarée avec le modificateur unsafe :

---------

La portée du contexte unsafe s'étend de la liste de paramètres à la fin de la méthode, de sorte que les pointeurs peuvent également être utilisés dans la liste de paramètres :

---------

Vous pouvez également avoir recours à un bloc unsafe pour utiliser un code unsafe dans ce bloc. Par exemple :

-------

Pour compiler du code unsafe, vous devez spécifier l'option de compilateur /unsafe. Le code unsafe n'est pas vérifiable par le service CLR (Common Language Runtime).


Exemple


----------


virtual

Le mot clé virtual sert à modifier une méthode, une propriété, un indexeur ou une déclaration event et leur permet d'être substitués dans une classe dérivée. Par exemple, cette méthode peut être substituée par toute classe qui en hérite :

--------

L'implémentation d'un membre virtuel peut être modifiée par un membre de substitution dans une classe dérivée. Pour plus d'informations sur l'utilisation du mot clé virtual, consultez Gestion de version avec les mots clés override et new et Savoir quand utiliser les mots clés override et new.

Notes

Quand une méthode virtuelle est appelée, un membre de substitution est recherché dans le type d'objet au moment de l'exécution. Le membre de substitution de la classe la plus dérivée est appelé (cela peut être le membre d'origine), si aucune classe dérivée n'a substitué le membre.

Par défaut, les méthodes ne sont pas virtuelles. Vous ne pouvez pas substituer une méthode non virtuelle.

Vous ne pouvez pas utiliser le modificateur virtual avec les modificateurs static, abstract, private ou override. L'exemple suivant illustre une propriété virtuelle :

----------

Les propriétés virtuelles se comportent comme les méthodes abstraites, à l'exception des différences dans la syntaxe de déclaration et d'appel.

  • L'utilisation du modificateur virtual sur une propriété statique est une erreur.
  • Une propriété virtuelle héritée peut être substituée dans une classe dérivée en incluant une déclaration de propriété qui utilise le modificateur override.


Exemple

Dans cet exemple, la classe Shape contient les deux coordonnées x et y, ainsi que la méthode virtuelle Area(). Différentes classes de formes, telles que Circle, Cylinder et Sphere, héritent de la classe Shape, et la surface est calculée pour chaque figure. Chaque classe dérivée a sa propre implémentation de substitution de Area().

Notez que les classes héritées Circle, Sphere et Cylinder utilisent toutes des constructeurs qui initialisent la classe de base, comme indiqué dans la déclaration suivante.

--------

Le programme suivant calcule et affiche la zone appropriée pour chaque figure en appelant l'implémentation appropriée de la méthode Area(), selon l'objet associé à la méthode.

---------


volatile

Le mot clé volatile indique qu'un champ peut être modifié par plusieurs threads qui s'exécutent simultanément. Le compilateur, le système de runtime et même le matériel sont susceptibles de réorganiser les lectures et les écritures sur des emplacements de mémoire pour des raisons de performances. Les champs déclarés volatile ne sont pas soumis à ces optimisations. Le fait d'ajouter le modificateur volatile permet de garantir que tous les threads observent les écritures volatiles effectuées par un autre thread dans l'ordre dans lequel elles ont été effectuées. Rien ne garantit que les écritures volatiles présentent un ordre total unique, tel que le voient tous les threads d'exécution.

Le mot clé volatile peut être appliqué aux champs des types suivants :

  • Types référence.
  • Types pointeur (dans un contexte unsafe). Notez que, même si le pointeur lui-même peut être volatile, l'objet sur lequel il pointe ne le peut pas. En d'autres termes, vous ne pouvez pas déclarer un pointeur vers un objet volatile.
  • Types simples comme sbyte, byte, short, ushort, int, uint, char, float et bool.
  • Type enum avec l'un des types de base suivants : byte, sbyte, short, ushort, int ou uint.
  • Paramètres de type générique connus comme des types référence.
  • Voir IntPtr et UIntPtr.

Les autres types, notamment double et long, ne peuvent pas être marqués volatile, car il n'y a aucune garantie que les lectures et écritures sur des champs de ce type soient atomiques. Pour protéger l'accès multithread à ces types de champs, utilisez les membres de classe Interlocked ou l'instruction lock.

Le mot clé volatile ne peut s'appliquer qu'aux champs d'une class ou d'un struct. Les variables locales ne peuvent pas être déclarées volatile.


Exemple

L'exemple ci-dessous montre comment déclarer une variable de champ public comme volatile.

--------

L'exemple suivant montre comment il est possible de créer un thread auxiliaire ou de travail et de l'utiliser pour effectuer le traitement en parallèle avec le thread principal. Pour plus d'informations sur le multithreading, voir Threading managé.

----------

Si vous ajoutez le modificateur volatile à la déclaration de _shouldStop en place, vous obtiendrez toujours les mêmes résultats (similaires à l'extrait indiqué dans le code précédent). Sans ce modificateur sur le membre _shouldStop en revanche, le comportement est imprévisible. La méthode DoWork peut optimiser l'accès au membre, ce qui entraîne la lecture de données périmées. En raison de la nature de la programmation multithread, le nombre de lectures obsolètes est imprévisible. Différentes exécutions du programme produiront des résultats légèrement différents.