This article is currently in the process of being translated into French (~38% done).
Namespaces
Dans un article précédent, nous avons brièvement parlé des espaces de noms (de l'anglais namespaces). Vous reconnaissez probablement ce mot-clé puisque celui-ci se retrouve souvent dans des fichiers de code source C#, habituellement au début. Un espace de nom sert essentiellement à regrouper un ensemble de types (par exemple: des classes), au travers d'un espace de nommage qui lui est propre. Quand Visual Studio génère un nouveau projet pour vous, il génère aussi un espace de noms par défaut dans lequel se trouve le premier fichier (du moins, cela est vrai pour un projet de type Console App). Cela devrait ressembler à :
using System;
namespace MyProject
{
class Program
{
static void Main(string[] args)
{
// More code below this....
Dans cette exemple, le namespace "MyProject" est maintenant un élément de l'application et quand vous voudrez l'utiliser en dehors de celui-ci, vous aurez besoin de préfixer la classe par le nom du namespace. Vous pouvez constater exactement la même chose quand vous souhaitez utiliser quelques choses de profondément enfouit dans la librairie .NET, comme ceci :
System.IO.File.ReadAllText("test.txt");
Ici, on utilise la méthode ReadAllText() de la classe File qui existe dans le namespace System.IO. Bien entendu, il serait fastidieux de réécrire un nom si long à chaque que vous souhaitez utiliser une classe de ce namespace, donc C# vous permet "d'importer" un namespace entier dans votre fichier en utilisant le mot-clés using. Encore une fois, vous devriez connaitre ce terme, car on le retrouve souvent en haut des fichier C#. Si on reprend l'exemple du dessus et que vous auriez besoin de la classe File plus d'une fois, cela serait censé d'importer le namespace System.IO avec le mot-clés using comme ceci:
using System;
using System.IO;
// More using statements here...
Pourquoi a-t-on besoin des espaces de noms ?
If you have just started programming, you might wonder what we need namespaces for. Why not just put all your classes in the same namespaces so that they are always accessible? You have a valid point, but only if your project is very small. As soon as you start adding more and more classes, it makes very good sense to separate them into namespaces. It simply makes it easier for you to find your code, especially if you places your files in corresponding folders - in fact, if you add a folder to your project and then add a class to it, Visual Studio will automatically put it in a corresponding namespace. So, if you create a folder in MyProject called MyFolder, classes added to this folder will, by default, be placed in a namespace called MyProject.MyFolder.
Une bonne manière de comprendre la nécessité d'utiliser des espaces de noms peut être trouvée au sein du framework .NET lui-même. Imaginez ce qu'il se passerait si tous les classes se situaient dans l'espace de noms global, ce serait un bazar ! A la place, elles sont rangées en utilisant System comme espace de nom de départ pour la plupart d'entre elles, puis des sous-espaces de noms comme System.IO pour l'entrée et la sortie, System.Net pour des choses en lien avec le réseau et System.Net.Mail pour les mails.
Name Conflicts with Namespaces
As mentioned, namespaces are also there to encapsulate your types (usually classes), so that they can exist within their own domain. This also means that you are free to create classes with the same name as the ones found elsewhere in your project or even in the .NET framework. For instance, you might decide that you need a File class of your own. As we saw in the previous examples, such a class already exists in the System.IO namespace, but you are free to create one in your own namespace, like this:
using System;
namespace MyProject.IO
{
class File
{
public static void HelloWorld()
{
Console.WriteLine("Hello, world!");
}
}
}
Now when you want to use it in your project, e.g. in your Program.cs Main method (if you're working on a Console App, like I am), you can either write the full name:
MyProject.IO.File.HelloWorld();
But you can also import the namespace, like you can with any other namespace (built-in or user-defined), thanks to the using statement. Here's a more complete example:
using System;
using MyProject.IO;
namespace MyProject
{
class Program
{
static void Main(string[] args)
{
File.HelloWorld();
}
}
}
So far, so good! However, what if you also want to use the File class from the System.IO namespace? Well, this is where the trouble starts, because if you import that namespace as well, with a using statement, the compiler no longer knows which File class you're referring to - our own or the one from the System.IO namespace. This can be solved by only importing one of the namespaces (ideally the one from which you use the most types) and then fully qualifying the name of the other one, like in this example:
using System;
using System.IO;
namespace MyProject
{
class Program
{
static void Main(string[] args)
{
MyProject.IO.File.HelloWorld();
}
}
}
But it's a bit cumbersome to type each time, especially if your class is even deeper nested in namespaces, e.g. MyProject.FileStuff.IO.File. Fortunately, C# has a solution for that.
Using Alias Directive
To shorten the name of the namespace a lot, you can import the namespace under a different name, with a Using Alias Directive. Notice how I do just that in the next example:
using System;
using System.IO;
using MyIO = MyProject.IO;
namespace MyProject
{
class Program
{
static void Main(string[] args)
{
File.ReadAllText("test.txt");
MyIO.File.HelloWorld();
}
}
}
The magic happens in the third line, where I pull in the MyProject.IO namespace and give it a shorter name (MyIO), which can then be used when we want to access types from it. At this point, we're not saving a lot of keystrokes, but again you should imagine even longer names and levels of namespaces, and believe me, they can get quite long and nested.
Summary
Namespaces gives you the opportunity to encapsulate your types into "named spaces", which allows you to get a better structure in your code, as well as have multiple classes with the same name, as long as they exist in separate namespaces.