Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Les éléments ignorés sont des variables d’espace réservé, qui sont inutilisées de façon intentionnelle dans le code d’une application. Les abandons sont équivalents à des variables non attribuées ; ils n’ont pas de valeur. Un rejet indique au compilateur et à d'autres personnes qui lisent votre code que vous souhaitez ignorer le résultat d'une expression. Vous pouvez ignorer le résultat d’une expression, d’un ou de plusieurs membres d’une expression tuple, d’un out
paramètre d’une méthode ou de la cible d’une expression correspondante de modèle.
Les éléments ignorés permettent de clarifier l’objectif de votre code. Un abandon indique que notre code n’utilise jamais la variable. Ils améliorent sa lisibilité et sa facilité de maintenance.
Vous indiquez qu’une variable est à ignorer en lui attribuant le trait de soulignement (_
) comme nom. Par exemple, l’appel de méthode suivant retourne un tuple, où la première et la seconde valeurs sont des éléments ignorés.
area
est une variable précédemment déclarée définie sur le troisième composant retourné par GetCityInformation
:
(_, _, area) = city.GetCityInformation(cityName);
Vous pouvez utiliser les éléments ignorés pour spécifier les paramètres d’entrée inutilisés d’une expression lambda. Pour plus d’informations, consultez les paramètres d’entrée d’une section d’expression lambda de l’article expressions lambda .
Lorsqu’un _
est un abandon valide, tenter de récupérer sa valeur ou de l'utiliser dans une opération d'assignation génère l’erreur du compilateur CS0103, « Le nom '_' n’existe pas dans le contexte actuel ». Cette erreur est due au fait que _
n’est pas affecté à une valeur et peut même ne pas être affecté à un emplacement de stockage. S’il s’agissait d’une variable réelle, vous n’avez pas pu ignorer plusieurs valeurs, comme l’a fait l’exemple précédent.
Déconstruction de tuple et d’objet
Les éléments ignorés sont utiles pour travailler avec des tuples quand le code de votre application utilise certains éléments d’un tuple, mais ignore les autres. Par exemple, la méthode suivante QueryCityDataForYears
retourne un tuple avec le nom d’une ville, sa zone, une année, la population de la ville pour cette année, une deuxième année et la population de la ville pour cette deuxième année. L’exemple montre la différence de population entre ces deux années. Parmi les données disponibles dans le tuple, nous ne sommes pas intéressés par la région de la ville, et nous connaissons le nom de la ville et les deux dates au moment du design. Par conséquent, nous sommes intéressés seulement par les deux valeurs de la population stockées dans le tuple et nous pouvons gérer ses valeurs restantes comme éléments ignorés.
var (_, _, _, pop1, _, pop2) = QueryCityDataForYears("New York City", 1960, 2010);
Console.WriteLine($"Population change, 1960 to 2010: {pop2 - pop1:N0}");
static (string, double, int, int, int, int) QueryCityDataForYears(string name, int year1, int year2)
{
int population1 = 0, population2 = 0;
double area = 0;
if (name == "New York City")
{
area = 468.48;
if (year1 == 1960)
{
population1 = 7781984;
}
if (year2 == 2010)
{
population2 = 8175133;
}
return (name, area, year1, population1, year2, population2);
}
return ("", 0, 0, 0, 0, 0);
}
// The example displays the following output:
// Population change, 1960 to 2010: 393,149
Pour plus d’informations sur la déconstruction de tuples avec des éléments ignorés, consultez Déconstruction de tuples et d’autres types.
La Deconstruct
méthode d’une classe, d’une structure ou d’une interface vous permet également de récupérer et de déconstructer un ensemble spécifique de données à partir d’un objet. Vous pouvez utiliser des éléments ignorés quand vous êtes intéressé seulement par un sous-ensemble des valeurs déconstruites. L’exemple suivant décompose un Person
objet en quatre chaînes (prénom, nom, ville et région), mais les nom et région sont ignorés.
using System;
namespace Discards
{
public class Person
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string City { get; set; }
public string State { get; set; }
public Person(string fname, string mname, string lname,
string cityName, string stateName)
{
FirstName = fname;
MiddleName = mname;
LastName = lname;
City = cityName;
State = stateName;
}
// Return the first and last name.
public void Deconstruct(out string fname, out string lname)
{
fname = FirstName;
lname = LastName;
}
public void Deconstruct(out string fname, out string mname, out string lname)
{
fname = FirstName;
mname = MiddleName;
lname = LastName;
}
public void Deconstruct(out string fname, out string lname,
out string city, out string state)
{
fname = FirstName;
lname = LastName;
city = City;
state = State;
}
}
class Example
{
public static void Main()
{
var p = new Person("John", "Quincy", "Adams", "Boston", "MA");
// Deconstruct the person object.
var (fName, _, city, _) = p;
Console.WriteLine($"Hello {fName} of {city}!");
// The example displays the following output:
// Hello John of Boston!
}
}
}
Pour plus d’informations sur la déconstruction de types définis par l’utilisateur avec des éléments ignorés, consultez Déconstruction de tuples et d’autres types.
Utilisation des critères spéciaux avec switch
Le modèle d’élément ignoré peut être utilisé dans des critères spéciaux avec l’expression de commutateur. Chaque expression, y compris null
, correspond toujours au modèle d’abandon.
L’exemple suivant définit une méthode qui utilise une ProvidesFormatInfo
switch
expression pour déterminer si un objet fournit une IFormatProvider implémentation et teste si l’objet est null
. Il utilise également le modèle de rejet pour gérer les objets non-null de tout autre type.
object?[] objects = [CultureInfo.CurrentCulture,
CultureInfo.CurrentCulture.DateTimeFormat,
CultureInfo.CurrentCulture.NumberFormat,
new ArgumentException(), null];
foreach (var obj in objects)
ProvidesFormatInfo(obj);
static void ProvidesFormatInfo(object? obj) =>
Console.WriteLine(obj switch
{
IFormatProvider fmt => $"{fmt.GetType()} object",
null => "A null object reference: Its use could result in a NullReferenceException",
_ => "Some object type without format information"
});
// The example displays the following output:
// System.Globalization.CultureInfo object
// System.Globalization.DateTimeFormatInfo object
// System.Globalization.NumberFormatInfo object
// Some object type without format information
// A null object reference: Its use could result in a NullReferenceException
Appels aux méthodes avec un paramètre out
Lorsque vous appelez la Deconstruct
méthode pour déconstructer un type défini par l’utilisateur (instance d’une classe, d’une structure ou d’une interface), vous pouvez ignorer les valeurs des arguments individuels out
. Toutefois, vous pouvez également laisser de côté la valeur des out
arguments lorsque vous appelez toute méthode avec un out
paramètre.
L’exemple suivant appelle la méthode DateTime.TryParse(String, out DateTime) pour déterminer si la représentation sous forme de chaîne d’une date est valide dans la culture actuelle. Étant donné que l’exemple s’intéresse uniquement à la validation de la chaîne de date et non à l’analyse pour extraire la date, l’argument out
de la méthode est un abandon.
string[] dateStrings = ["05/01/2018 14:57:32.8", "2018-05-01 14:57:32.8",
"2018-05-01T14:57:32.8375298-04:00", "5/01/2018",
"5/01/2018 14:57:32.80 -07:00",
"1 May 2018 2:57:32.8 PM", "16-05-2018 1:00:32 PM",
"Fri, 15 May 2018 20:10:57 GMT"];
foreach (string dateString in dateStrings)
{
if (DateTime.TryParse(dateString, out _))
Console.WriteLine($"'{dateString}': valid");
else
Console.WriteLine($"'{dateString}': invalid");
}
// The example displays output like the following:
// '05/01/2018 14:57:32.8': valid
// '2018-05-01 14:57:32.8': valid
// '2018-05-01T14:57:32.8375298-04:00': valid
// '5/01/2018': valid
// '5/01/2018 14:57:32.80 -07:00': valid
// '1 May 2018 2:57:32.8 PM': valid
// '16-05-2018 1:00:32 PM': invalid
// 'Fri, 15 May 2018 20:10:57 GMT': invalid
Élément ignoré autonome
Vous pouvez utiliser un abandon autonome pour indiquer toute variable que vous choisissez d’ignorer. L’une des utilisations courantes consiste à utiliser une affectation pour s’assurer qu’un argument n’est pas null. Le code suivant utilise un élément ignoré pour forcer une affectation. Le côté droit de l’affectation utilise l’opérateur de fusion null pour lever un System.ArgumentNullException lorsque l’argument est null
. Le code n’a pas besoin du résultat de l’affectation. Il est donc ignoré. L’expression force une vérification null. L’élément ignoré clarifie votre intention : le résultat de l’affectation n’est ni nécessaire ni utilisé.
public static void Method(string arg)
{
_ = arg ?? throw new ArgumentNullException(paramName: nameof(arg), message: "arg can't be null");
// Do work with arg.
}
L’exemple suivant utilise un abandon autonome pour ignorer l’objet Task retourné par une opération asynchrone. Attribuer la tâche a pour effet de supprimer l’exception que l’opération lève au moment où elle est sur le point de se terminer. Cela rend votre intention claire : vous souhaitez ignorer l’opération Task
asynchrone et ignorer les erreurs générées à partir de cette opération asynchrone.
private static async Task ExecuteAsyncMethods()
{
Console.WriteLine("About to launch a task...");
_ = Task.Run(() =>
{
var iterations = 0;
for (int ctr = 0; ctr < int.MaxValue; ctr++)
iterations++;
Console.WriteLine("Completed looping operation...");
throw new InvalidOperationException();
});
await Task.Delay(5000);
Console.WriteLine("Exiting after 5 second delay");
}
// The example displays output like the following:
// About to launch a task...
// Completed looping operation...
// Exiting after 5 second delay
Sans affecter la tâche à un abandon, le code suivant génère un avertissement du compilateur :
private static async Task ExecuteAsyncMethods()
{
Console.WriteLine("About to launch a task...");
// CS4014: Because this call is not awaited, execution of the current method continues before the call is completed.
// Consider applying the 'await' operator to the result of the call.
Task.Run(() =>
{
var iterations = 0;
for (int ctr = 0; ctr < int.MaxValue; ctr++)
iterations++;
Console.WriteLine("Completed looping operation...");
throw new InvalidOperationException();
});
await Task.Delay(5000);
Console.WriteLine("Exiting after 5 second delay");
Remarque
Si vous exécutez l’un des deux exemples précédents à l’aide d’un débogueur, le débogueur arrête le programme lorsque l’exception est levée. Sans débogueur attaché, l’exception est ignorée silencieusement dans les deux cas.
_
est également un identificateur valide. Lorsqu’elle est utilisée en dehors d’un contexte pris en charge, _
est traitée non pas comme une mise au rebut, mais comme une variable valide. Si un identificateur nommé _
est déjà dans l’étendue, l’utilisation de _
comme élément ignoré autonome peut provoquer :
- Une modification accidentelle de la valeur de la variable
_
dans l’étendue en lui affectant la valeur de l’élément ignoré prévu. Par exemple:private static void ShowValue(int _) { byte[] arr = [0, 0, 1, 2]; _ = BitConverter.ToInt32(arr, 0); Console.WriteLine(_); } // The example displays the following output: // 33619968
- Erreur du compilateur pour violation de la sécurité de type. Par exemple:
private static bool RoundTrips(int _) { string value = _.ToString(); int newValue = 0; _ = Int32.TryParse(value, out newValue); return _ == newValue; } // The example displays the following compiler error: // error CS0029: Cannot implicitly convert type 'bool' to 'int'