TOC

This article is currently in the process of being translated into French (~55% done).

Classes:

Propriétés

Dans l'article précédent, nous avons parlé des champs. Ils sont comme des variables globales pour une classe, vous permettant leur accès dans toutes les méthodes. Nous avons aussi brièvement évoqué le fait que l'on peut accéder aux champs depuis d'autres classes s'ils sont identifiés comme public, mais cela n'est généralement pas recommandé. Pour les variables/champs auxquels vous voudriez avoir accès depuis l'extérieur de votre classe, vous devriez plutôt utiliser les propriétés.

Quand vous déclarez un champ comme public, vous y donnez un accès complet depuis l'extérieur - d'autres classes pouvant en faire ce qu'elles veulent, sans autre notification à la classe déclarante. Les Propriétés rendent le contrôle à la classe déclarante, en spécifiant qu'un champ est en lecture ou en écriture seule et permet à la classe déclarante de vérifier et manipuler sa valeur avant de la renvoyer ou de l'assigner au champ.

Une propriété ressemble un peu à un hybride de champ et de méthode, parce qu'en plus d'être déclaré comme un champ avec sa visibilité, son type de donnée, il dispose aussi d'un contenu, comme une méthode, pour en contrôler le comportement.

public string Name
{
	get { return _name; }
	set { _name = value; }
}

Notez les mots-clés get et set. Ils sont utilisés exclusivement pour les propriétés, pour contrôler le comportement lors de la lecture (get'in) et de l'écriture (set'in) du champ. Vous pouvez avoir des propriétés implémentant seulement la lecture ou seulement l'écriture, pour créer des propriétés en lecture seule ou en écriture seule, et vous pouvez même contrôler la visibilité des implémentations get et set, par exemple pour créer une propriété qui puisse être lue depuis n'importe où (public), mais modifiée uniquement depuis l'intérieur de la classe déclarante (private).

Vous noterez aussi que je fais référence à un champ nommé _name. Vous aurez également à déclarer cela dans votre classe, de sorte que votre propriété puisse l'utiliser. Un format communément admis pour les champs et propriétés ressemblera à ceci :

private string _name = "John Doe";

public string Name
{
	get { return _name; }
	set { _name = value; }
}

Vous pouvez maintenant voir comment le champ et la propriété fonctionnent ensembles: La méthode get va retourner la valeur du champ _name, alors que la méthode set va assigner la valeur qui a été donnée au champ _name. Dans la méthode set, on utilise le mot clé spécial value qui, dans ce cas, vas référer à la valeur passée à la propriété.

Donc, c'est à peu près aussi basique que possible et à ce stade, nous ne faisons rien qui ne puisse être accompli avec un simple champ public. Mais à un stade ultérieur, vous pouvez décider que vous souhaitez prendre plus de contrôle sur la façon dont les autres classes peuvent travailler avec le nom et puisque vous l'avez implémenté en tant que propriété, vous êtes libre de modifier l'implémentation sans déranger quiconque utilise votre classe. Par exemple, la propriété Name pourrait être modifiée pour ressembler à ceci:

private string _name = "John Doe";

public string Name
{
	get 
	{
		return _name.ToUpper();
	}
	set 
	{
		if(!value.Contains(" "))
			throw new Exception("Please specify both first and last name!");
		_name = value; 
	}
}

La méthode get impose désormais que la valeur renvoyée soit toujours en MAJUSCULES, quelle que soit la casse du champ de sauvegarde (_name). Dans la méthode set, nous avons ajouté un quelques lignes de code pour vérifier si la valeur passée contient un espace, car nous avons décidé que le nom doit toujours être composé à la fois d'un prénom et d'un nom - si ce n'est pas le cas, une exception est levée. Tout cela est très grossier et simplifié, mais cela devrait illustrer le niveau de contrôle total que vous obtenez lorsque vous utilisez des propriétés.

Read-only properties

La plupart des propriétés que vous verrez dans les exemples de ce didacticiel seront à la fois lisibles et inscriptibles, car c'est l'utilisation la plus courante des propriétés, mais cela ne doit pas toujours être le cas. Tout d'abord, vous pouvez déclarer une propriété avec seulement une méthode-get, comme ceci :

private string _name = "John Doe";

public string Name
{
	get { return _name; }
}

In this case, you can no longer change the "Name" property - you can only read it and the compiler will throw an error if you try to assign a value to it. You can still change the value of it from inside the class though, since you can simply assign a new value to the backing field "_name". Doing it that way kind of negates one of the biggest advantage to properties though: The ability to always control whether a value can be accepted. As we already talked about, the set-method is a great way to perform validation of the value, but if you assign a new value to the _name field from multiple places, because the property is read-only, you don't get this validation.

Fortunately for us, C# offers a solution to this: You can define a set method on the property, but limit its visibility, using e.g. the private or the protected keyword. This will give you the best of both worlds, where you can still assign a value to the property from inside the class (or any inherited class if you use the protected keyword) and have it validated accordingly. Here's an example:

private string _name = "John Doe";

public string Name
{
	get { return _name; }

	private set
	{
		if(IsValidName(value))
			this._name = value;
	}
}

public bool IsValidName(string name)
{
	return name.EndsWith("Doe");

}

The key difference here is simply the "private" keyword right in front of the "set" keyword, and as mentioned, you can replace it with e.g. protected or internal, depending on your needs.

Auto-implemented properties

In some cases, you don't need all the control over a field and it can feel cumbersome to implement both a field and a property with the get and set methods not doing anything besides what we saw in the first example. You may be tempted to simply declare your variable as a public field to avoid all this extra hassle. But don't do that! Fortunately for all of us, Microsoft decided to add auto-implemented properties in C# version 3, which will save you several lines of code. Just consider the difference:

Regular property with a declared backing field:

private string _name;

public string Name
{
	get { return _name; }
	set { _name = value; }
}

The exact same behavior, but with an auto-implemented property:

public string Name { get; set; }

Notice that the get and set methods are empty and that no private backing field is declared - in other words, we can now accomplish the exact same behavior as in the first example but with a single line of code! Bear in mind that the private backing field will still exist at runtime - it will be auto-implemented by the compiler, as the name implies. Should you later decide that you need more control of this specific property, you can simply change it to a regular field/property combination with the desired implementation of the get and set methods.

Notice that you are still left with an important mechanism of control from regular properties when using auto-implemented properties: You can leave out the set keyword to create a read-only property, e.g. like this:

public string ReadOnlyProperty { get; }

Les propriétés en écriture seule ne sont pas autorisées lorsqu'on utilise des propriétés auto-implémentées.

Propriétés auto-implémentées avec valeur par défaut

Avant la version 6 de C#, vous ne pouviez pas définir une valeur par défaut pour une propriété auto-implémentée. Pour cela, vous deviez déclarer un champ complémentaire, ce qui vous permettait d'initialiser la variable avec une valeur :

private string _name = "John Doe";

public string Name
{
	get { return _name; }
	set { _name = value; }
}

Mais dans la version 6 de C#, Microsoft a enfin ajouté la possibilité d'initialiser une propriété auto-implémentée avec une valeur par défaut, comme ceci :

public string Name { get; set; } = "John Doe";

Expression-bodied properties

Another property-related feature Microsoft implemented in C# 6.0 and 7.0 is the expression bodied members. It simply allows you to write single-line expressions for your properties and methods - in this case, let's look at how to use it for your get/set methods in a way that takes up less space and requires slightly less typing:

private string name;
public string Name
{
	get => name;
	set => name = value;
}

If your property is read-only, the syntax can be even shorter:

public string Name => "John Doe";

Of course this also works if you need to actually do something before returning the value, like this:

public string Name { get; set; } = "John Doe";

public string FirstName => this.Name.Substring(0, this.Name.IndexOf(" "));

As you can see, this allows you to define a get method but without the actual get and return keywords, while encouraging you to keep it all in one line instead of multiple lines.

Résumé

Les propriétés octroient à vos classes plus de contrôle sur la manière dont les champs peuvent être accédés et manipulés, et elles doivent toujours être utilisées lorsque vous souhaitez donner accès à des champs en dehors de la classe déclarante.

This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!