Comment éliminer explicitement un argument de sortie?

Je fais un appel:

myResult = MakeMyCall(inputParams, out messages); 

mais je ne me soucie pas vraiment des messages. Si c’était un paramètre d’entrée, je me fichais de passer un null. Si c’était le retour, je m’en foutais.

Est-il possible de faire quelque chose de similaire avec un out, ou dois-je déclarer une variable que je vais alors ignorer?

À partir de C # 7.0, il est possible d’éviter de prédéclarer les parameters et de les ignorer.

 public void PrintCoordinates(Point p) { p.GetCoordinates(out int x, out int y); WriteLine($"({x}, {y})"); } public void PrintXCoordinate(Point p) { p.GetCoordinates(out int x, out _); // I only care about x WriteLine($"{x}"); } 

Source: https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/

Vous devez déclarer une variable que vous ignorerez alors. C’est le cas le plus souvent avec le modèle TryParse (ou TryWhatever), lorsqu’il est utilisé pour tester la validité de l’entrée utilisateur (par exemple, peut-il être analysé sous forme de nombre?) Sans se soucier de la valeur analysée réelle.

Vous avez utilisé le mot “disposer” dans la question, ce qui, je pense, était malheureux – mais si le paramètre out est d’un type qui implémente IDisposable, vous devriez certainement appeler Dispose à moins que la documentation de la méthode n’indique explicitement que recevoir la valeur ne confère pas la possession. Je ne me souviens pas avoir vu une méthode avec un paramètre jetable, donc j’espère que ce n’était qu’un choix de mots malchanceux.

Malheureusement, vous devez passer quelque chose car la méthode est nécessaire pour la définir. Vous ne pouvez donc pas envoyer de données null car la méthode, qui est nécessaire pour la définir, va exploser.

Une approche pour masquer la laideur consisterait à envelopper la méthode dans une autre méthode qui fait le paramètre out pour vous:

 Ssortingng Other_MakeMyCall(Ssortingng inputParams) { Ssortingng messages; return MakeMyCall(inputParams, out messages); } 

Vous pouvez ensuite appeler Other_MakeMyCall sans avoir à Other_MakeMyCall out parameters Other_MakeMyCall .

Si la fonction d’origine est déclarée comme ceci:

 class C { public Result MakeMyCall(Object arg, out List messages); } 

Vous pouvez déclarer une méthode d’extension comme ceci:

 static class CExtension { public static Result MakeMyCall(this C obj, Object arg) { List unused; return obj.MakeMyCall(arg, out unused); } } 

La méthode d’extension se comportera comme une surcharge qui rend le paramètre out facultatif.

Le compilateur Visual Basic fait cela en créant une variable factice. C # pourrait le faire, si vous pouvez convaincre Microsoft que c’est une bonne idée.

Si la classe de messages implémente IDisposable , vous ne devez pas l’ignorer. Considérons quelque chose comme l’approche suivante (peut-être pas syntaxiquement correct puisque je n’ai pas écrit C # depuis un moment):

 using (FooClass messages) { myResult = MakeMyCall(inputParams, messages); } 

Une fois hors du bloc, les messages seront automatiquement éliminés.

Vous devez passer une variable pour le paramètre out. Vous n’avez pas à initialiser la variable avant de la passer:

 MyMessagesType messages; myResult = MakeMyCall(inputParams, out messages); 

En règle générale, vous pouvez simplement ignorer les «messages» après l’appel – à moins que les messages ne soient supprimés pour une raison quelconque, comme l’utilisation de ressources système limitées, auquel cas vous devez appeler Dispose ():

 messages.Dispose(); 

S’il peut utiliser une quantité importante de mémoire et qu’il restra dans la scope pendant un certain temps, il devrait probablement être défini sur null s’il s’agit d’un type de référence ou sur une nouvelle instance par défaut s’il s’agit d’un type de valeur. le collecteur peut récupérer la mémoire:

 messages = null; // Allow GC to reclaim memory for reference type. messages = new MyMessageType(); // Allow GC to reclaim memory for value type. 

Dans ce cas, j’ai effectué une méthode d’extension générique pour ConcurrentDictionary qui ne possède pas de méthode Delete ou Remove.

 //Remove item from list and ignore reference to removed item public static void TryRemoveIgnore(this ConcurrentDictionary dictionary, K key) { T CompletelyIgnored; dictionary.TryRemove(key, out CompletelyIgnored); } 

Appelé par une instance de ConcurrentDictionary:

 ClientList.TryRemoveIgnore(client.ClientId);