Chaque type .NET a un nom complet composé d'un namespace et du nom du type : System.Console, System.Collections.Generic.List<T>, System.Text.StringBuilder. Les namespaces regroupent les types apparentés et évitent les conflits de noms, si bien que votre propre classe Order ou Timer peut coexister avec celles des bibliothèques. La directive using en haut d'un fichier importe un namespace pour que vous puissiez utiliser les noms courts.
Sortie :
Cart: tea, honey
1
Une directive using n'agit que sur les noms à la compilation. Elle ne charge aucune bibliothèque et n'ajoute pas de code au programme ; les bibliothèques disponibles sont déterminées par les références du projet et les packages NuGet. Si le compilateur signale qu'un type ou un namespace « could not be found (are you missing a using directive or an assembly reference?) », erreur CS0246, c'est que la ligne using manque ou que le package n'est pas référencé.
Déclarer vos propres namespaces
Placez les types dans un bloc namespace. Les namespaces peuvent être imbriqués, s'écrire avec des points, et un même namespace peut être réparti sur plusieurs fichiers.
Sortie :
120.00 via DHL
Shop.Billing.Invoice
namespace Shop.Billing { } est un raccourci pour namespace Shop { namespace Billing { } }. Le code situé dans Shop peut désigner Billing.Invoice sans le préfixe Shop., car les noms sont d'abord recherchés dans les namespaces englobants.
Conventions : commencez par l'entreprise ou le produit (Contoso.Payments), puis la fonctionnalité ou la couche, et suivez l'arborescence des dossiers (Contoso.Payments/Refunds/RefundService.cs contient Contoso.Payments.Refunds). Ne donnez jamais à une classe le nom de son namespace (Shop.Shop), ce qui impose des qualifications maladroites partout.
Les alias
using Name = Namespace.Type; donne un nom local à un type (ou à un namespace). Deux situations s'y prêtent : raccourcir un long type générique et résoudre un conflit.
Sortie :
latte: 3.60
order 17
Les alias ne s'appliquent qu'au fichier où ils sont déclarés (sauf s'ils sont global, voir plus bas). Depuis C# 12, un alias peut nommer n'importe quel type, y compris les tuples et les tableaux : using Point = (int X, int Y);.
Les références ambiguës (CS0104)
Quand deux namespaces importés contiennent un type du même nom, utiliser le nom court est une erreur. Le cas classique est Timer, qui existe dans System.Threading, System.Timers et (dans les applications de bureau) System.Windows.Forms :
using System.Threading;
using System.Timers;
var t = new Timer(1000);
// error CS0104: 'Timer' is an ambiguous reference between
// 'System.Timers.Timer' and 'System.Threading.Timer'
Trois corrections, de la plus locale à la moins locale : écrire le nom complet (new System.Timers.Timer(1000)), ajouter un alias qui indique celui que vous voulez, ou supprimer la directive dont vous n'avez pas besoin.
Sortie :
250
System.Timers.Timer
System.Threading.Timer
Si votre propre namespace définit un type appelé System ou Console, le préfixe global:: force la recherche depuis la racine : global::System.Console.WriteLine("hi");. Le code généré l'utilise partout pour cette raison.
using static
using static importe les membres statiques d'un seul type, pour qu'on puisse les appeler sans le nom du type. Cela convient au code qui appelle sans cesse la même classe, comme Math :
Sortie :
Area: 28.27
Hypotenuse: 5
42
using static fonctionne aussi avec les enums (using static System.DayOfWeek; permet d'écrire Monday) et avec vos propres classes statiques. Utilisez-le là où les noms courts restent sans ambiguïté ; un WriteLine seul dans un gros fichier peut laisser le lecteur se demander de quel writer il s'agit.
global using et namespaces de portée fichier (C# 10)
Deux fonctionnalités de C# 10 réduisent le code répétitif en haut des fichiers. Un global using s'applique à tous les fichiers du projet et se place en général dans un seul fichier comme GlobalUsings.cs :
// GlobalUsings.cs, C# 10 and later
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using Money = System.Decimal;
Les projets SDK .NET 6 et plus peuvent les générer pour vous. Avec <ImplicitUsings>enable</ImplicitUsings> dans le .csproj (la valeur par défaut des nouveaux modèles), un projet console reçoit System, System.Collections.Generic, System.IO, System.Linq, System.Net.Http, System.Threading et System.Threading.Tasks ; les projets web reçoivent en plus les namespaces ASP.NET Core. C'est pourquoi les fichiers Program.cs modernes commencent directement par du code.
Un namespace de portée fichier déclare le namespace pour tout le fichier avec un point-virgule au lieu d'un bloc, ce qui économise un niveau d'indentation :
// C# 10 and later
namespace Shop.Billing;
public class Invoice
{
public decimal Amount { get; set; }
}
Un fichier ne peut avoir qu'un seul namespace de portée fichier, et on ne peut pas le mélanger avec des namespaces en bloc dans le même fichier. Les projets plus anciens, les scripts Unity et le code qui cible .NET Framework utilisent la forme en bloc vue plus haut.
Où placer les directives using, et l'instruction using
Les directives using doivent précéder toute déclaration de namespace ou de type dans le fichier (les usings globaux avant tout le reste). On peut aussi les placer dans un bloc namespace, auquel cas elles ne s'appliquent que là ; les guides de style divergent, et la plupart du code .NET les garde en haut.
Le mot-clé using a un second rôle, sans rapport, à l'intérieur des méthodes : l'instruction using using (var file = File.OpenRead(path)) { ... } appelle Dispose sur l'objet à la fin du bloc, ce qui ferme fichiers et connexions. Elle partage le mot-clé et rien d'autre. Voir la page instruction using.
Questions fréquentes
À quoi sert using en C# ?
En haut d'un fichier, using System.Text; est une directive qui importe un namespace, ce qui permet d'écrire StringBuilder au lieu de System.Text.StringBuilder. Elle n'ajoute aucun code et ne charge rien ; elle raccourcit seulement les noms. Dans une méthode, using (var f = ...) est une autre fonctionnalité, l'instruction using, qui libère un objet à la fin d'un bloc.
Qu'est-ce qu'un namespace en C# ?
Un namespace (espace de noms) est un groupe nommé de types qui évite les conflits de noms et organise le code, comme System.Collections.Generic ou MyShop.Billing. Deux classes peuvent porter le même nom si elles sont dans des namespaces différents. Par convention, les namespaces suivent l'arborescence des dossiers et commencent par le nom de l'entreprise ou du produit.
Qu'est-ce que using static en C# ?
using static System.Math; importe les membres statiques d'un type, ce qui permet d'appeler Sqrt(16) et de lire PI sans le préfixe Math.. Cela fonctionne avec n'importe quelle classe, y compris les vôtres et les enums. Utilisez-le là où les noms courts restent clairs, comme dans du code très mathématique.
Comment corriger « is an ambiguous reference » en C# ?
L'erreur CS0104 signifie que deux namespaces importés contiennent chacun un type portant ce nom, par exemple Timer dans System.Threading et System.Timers. Écrivez le nom complet (System.Timers.Timer), supprimez l'une des directives using, ou ajoutez un alias : using Timer = System.Timers.Timer;.
Qu'est-ce que global using en C# ?
global using System.Text; (C# 10) importe un namespace pour tous les fichiers du projet, pas seulement celui où il apparaît. Les projets SDK .NET 6 et plus génèrent automatiquement un ensemble de usings globaux quand <ImplicitUsings>enable</ImplicitUsings> est défini, c'est pourquoi les nouveaux fichiers Program.cs n'ont aucune ligne using.