Une classe est un type que vous définissez : elle regroupe des données (les champs) et le code qui travaille sur ces données (les méthodes). Un objet est une instance d'une classe, créée à l'exécution avec new. Une classe, de nombreux objets, chacun avec ses propres valeurs.
Déclarer une classe et créer des objets
Une déclaration de classe liste ses membres entre accolades. Les champs contiennent les données, les méthodes le comportement. new ClassName() alloue un objet et vous donne une référence vers lui.
Sortie :
Maya: 120.50
Omar: 40
Withdraw 200 succeeded: False
Chaque objet a ses propres Owner et Balance. Dans une méthode, Balance signifie « le solde de l'objet sur lequel cette méthode a été appelée », c'est pourquoi maya.Deposit et omar.Deposit modifient des nombres différents. Cet objet implicite est disponible sous le nom this quand vous avez besoin de le nommer.
Les champs que vous n'affectez pas commencent à leur valeur par défaut : 0 pour les nombres, false pour bool, et null pour les chaînes et les autres types classe.
Les membres sont ici public pour que Main puisse y accéder. Les vraies classes gardent en général leurs champs private et exposent plutôt des propriétés ; la page sur les modificateurs d'accès en donne les règles. Une classe peut aussi déclarer un constructeur pour définir ses champs à la création de l'objet, ce que traite la page sur les constructeurs.
Une classe est un type référence
Une variable de type classe ne contient pas l'objet. Elle contient une référence vers un objet qui vit sur le tas. Affecter la variable copie la référence, donc deux variables peuvent pointer vers le même objet.
Sortie :
5
6
True
False
Trois conséquences apparaissent ici :
- Modifier l'objet via
secondest visible viafirst, car il n'y a qu'un seul objet. - Passer un objet à une méthode passe la référence. La méthode peut modifier les champs de l'objet et l'appelant le voit. (Affecter un nouvel objet au paramètre dans la méthode n'affecte pas la variable de l'appelant ; il faut pour cela
ref.) ==sur deux instances de classe compare par défaut les références : « est-ce le même objet ? », et non « ont-ils les mêmes valeurs ? ».lookalikea des données identiques et reste pourtant un objet différent.
Si vous voulez des copies à l'affectation et une comparaison par valeur, regardez les structs, qui sont des types valeur, ou les records, qui se comparent par valeur.
null et NullReferenceException
Une variable référence peut contenir null, qui signifie « aucun objet ». Utiliser un membre à travers null lève NullReferenceException, l'exception d'exécution la plus courante dans le code C#.
Sortie :
True
no city on file
NullReferenceException: Address was never set
Lisbon
La correction n'est presque jamais d'intercepter l'exception. Cherchez pourquoi la référence vaut null et créez l'objet plus tôt, vérifiez avant utilisation, ou utilisez l'opérateur conditionnel null ?., qui s'arrête et produit null au lieu de lever une exception. ?? fournit ensuite une valeur de repli. Ces deux opérateurs sont traités dans types nullables.
Redéfinir ToString
Chaque classe hérite de object, qui fournit ToString(). La version héritée renvoie le nom complet du type (y compris son namespace, s'il en a un), ce qui est rarement ce que vous voulez afficher. Redéfinissez-la :
Sortie :
Plain
Mug (8.50)
In cart: Mug (8.50)
Total line: Mug (8.50)
Console.WriteLine, l'interpolation de chaînes et + avec une chaîne appellent tous ToString() pour vous. Le débogueur l'affiche aussi, ce qui rend une redéfinition utile même si vous n'affichez jamais l'objet vous-même.
Initialiseurs d'objets
Un initialiseur d'objet définit des champs et propriétés publics juste après la construction de l'objet, dans la même expression. Il se lit mieux qu'une liste d'affectations et fonctionne bien dans les littéraux de collection.
Sortie :
A12: 25 (0 extras)
A13: 40 (2 extras)
Deux détails dans le second billet. Price = 40m remplace le 25m de l'initialiseur de champ, car l'initialiseur d'objet s'exécute après la construction de l'objet. Extras = { "Parking", "Poster" } n'a pas de new : il appelle Add sur la liste que le champ contient déjà, au lieu de la remplacer.
Un initialiseur d'objet n'est pas un constructeur. Il ne peut définir que des membres accessibles depuis le code appelant, et il ne peut pas garantir qu'un membre soit défini. Quand un objet est invalide sans certaines valeurs, exigez-les dans un constructeur.
Classes partielles
Le mot-clé partial répartit une classe sur plusieurs fichiers. Le compilateur fusionne les parties en une seule classe.
// Invoice.cs
public partial class Invoice
{
public decimal Subtotal;
public decimal Total() => Subtotal + Tax();
}
// Invoice.Tax.cs
public partial class Invoice
{
private decimal Tax() => Subtotal * 0.2m;
}
Chaque partie doit indiquer partial, être dans le même namespace et le même projet. L'usage courant est le code généré : les concepteurs WinForms, les générateurs de source et certains ORM écrivent une partie et vous laissent l'autre, si bien qu'une régénération n'écrase jamais votre code. Répartir une classe écrite à la main sur plusieurs fichiers dans le seul but de la raccourcir cache généralement une classe qui devrait en être deux.
Erreurs courantes
- Utiliser un objet avant de le créer. Un champ de type classe vaut
nulltant que vous ne lui affectez pasnew .... Le premier accès à un membre lèveNullReferenceException. - S'attendre à ce que l'affectation copie.
var b = a;pour une classe donne un second nom au même objet. Créez un nouvel objet et copiez les valeurs quand il vous en faut un indépendant. - Comparer des objets avec
==en s'attendant à une comparaison par valeur. Pour les classes,==compare les références, sauf si la classe surcharge==(comme le faitstring). Comparez les champs pertinents, ou redéfinissezEquals. - Afficher un objet et obtenir le nom de son type. Redéfinissez
ToString(). - Tout déclarer
public. Cela fonctionne dans de petits exemples, mais permet à n'importe quel code de mettre l'objet dans un état invalide, par exemple un solde négatif. Gardez les champs privés et modifiez-les via des méthodes qui vérifient les règles.
Questions fréquentes
Qu'est-ce qu'une classe en C# ?
Une classe est un type que vous définissez : un groupe nommé de données (champs et propriétés) et de comportements (méthodes). class Account { public decimal Balance; public void Deposit(decimal amount) { Balance += amount; } } en déclare une. Une classe est un plan ; elle ne fait rien tant que vous ne créez pas d'objets à partir d'elle avec new.
Quelle est la différence entre une classe et un objet en C# ?
La classe est la définition, écrite une seule fois dans le code source. Un objet en est une instance, créée à l'exécution avec new, avec sa propre copie de chaque champ d'instance. Deux appels à new Account() donnent deux objets de la même classe avec des soldes indépendants.
Comment créer un objet en C# ?
Utilisez new suivi du nom de la classe et des arguments du constructeur : var account = new Account();. Vous pouvez définir des champs et propriétés publics dans la même expression avec un initialiseur d'objet : new Account { Owner = "Maya" }. La variable contient une référence vers le nouvel objet, pas l'objet lui-même.
Pourquoi obtient-on une NullReferenceException en C# ?
Vous avez utilisé un membre (.Name, .Length, un appel de méthode) à travers une variable qui contient null, donc il n'y a aucun objet sur lequel agir. Les causes courantes sont un champ jamais affecté (les champs de type classe commencent à null), une recherche qui a renvoyé null, ou une méthode qui renvoie null en cas d'échec. Testez avec if (x != null), utilisez x?.Name, ou assurez-vous que l'objet est créé avant utilisation.
Comment redéfinir ToString en C# ?
Déclarez public override string ToString() dans votre classe et renvoyez le texte voulu, par exemple public override string ToString() => $"{Name} ({Price:F2})";. Sans cela, Console.WriteLine(obj) et l'interpolation de chaînes affichent le nom de la classe, car c'est ce que renvoie object.ToString().