Est-ce que C# 4.0 autorise des arguments out
ou ref
optionnels?
Avez-vous une idée pour une solution plus élégante que de déclarer temp/dummy?
Est-ce que C# 4.0 autorise des arguments out
ou ref
optionnels?
Non.
Une solution de contournement consiste à surcharger avec une autre méthode qui ne possède pas de paramètres out / ref, et qui appelle simplement votre méthode actuelle.
public bool SomeMethod(out string input)
{
...
}
// nouvelle surcharge
public bool SomeMethod()
{
string temp;
return SomeMethod(out temp);
}
Si vous avez C# 7.0, vous pouvez simplifier :
// nouvelle surcharge
public bool SomeMethod()
{
return SomeMethod(out _); // déclare out comme une variable de rejet inline
}
(Merci à @Oskar / @Reiner d'avoir souligné cela.)
Peut-être décent, mais élégant est définitivement sur une autre ligue. Le fait qu'il n'y ait pas de meilleure solution ne signifie pas que cela soit état de l'art par décret.
Comme déjà mentionné, ceci n'est tout simplement pas autorisé et je pense que cela n'a aucun sens. Cependant, pour ajouter quelques détails supplémentaires, voici une citation de la Spécification C# 4.0, section 21.1 :
Les paramètres formels des constructeurs, des méthodes, des indexeurs et des types de délégués peuvent être déclarés optionnels :
paramètre-fixe :
attributsopt modificateur-paramètreopt type identifiant argument-par-défautopt
argument-par-défaut :
= expression
- Un paramètre-fixe avec un argument-par-défaut est un paramètre optionnel, tandis qu'un paramètre-fixe sans un argument-par-défaut est un paramètre requis.
- Un paramètre requis ne peut pas apparaître après un paramètre optionnel dans une liste de paramètres formels.
- Un paramètre
ref
ouout
ne peut pas avoir d'argument-par-défaut.
Alternativement, vous pouvez créer une surcharge avec un paramètre ref/out. Oui, vous aurez deux définitions de fonctions, mais cela permettra d'obtenir ce que vous voulez.
Non, mais une autre excellente alternative consiste à utiliser la méthode d'une classe de modèle générique pour les paramètres facultatifs comme suit :
public class OptionalOut
{
public Type Result { get; set; }
}
Vous pouvez ensuite l'utiliser comme suit :
public string foo(string value, OptionalOut outResult = null)
{
// .. faire quelque chose
if (outResult != null) {
outResult.Result = 100;
}
return value;
}
public void bar ()
{
string str = "bar";
string result;
OptionalOut optional = new OptionalOut ();
// exemple : appel sans le paramètre facultatif de sortie
result = foo (str);
Console.WriteLine ("La sortie était {0} sans utilisation de la valeur facultative", result);
// exemple : l'appeler avec le paramètre facultatif
result = foo (str, optional);
Console.WriteLine ("La sortie était {0} avec la valeur facultative de {1}", result, optional.Result);
// exemple : l'appeler avec le paramètre facultatif nommé
foo (str, outResult: optional);
Console.WriteLine ("La sortie était {0} avec la valeur facultative de {1}", result, optional.Result);
}
C'est une solution très raisonnable, mais une chose à garder à l'esprit est que le compilateur ne forcera pas la nécessité que le paramètre de sortie soit assigné avant de quitter la méthode.
J'aime ça, mais si vous ne voulez pas créer une nouvelle classe, vous pouvez le simuler en passant un tableau à un seul élément.
Est-ce que quelqu'un pourrait s'il vous plaît élaborer là-dessus : "le compilateur n'imposera pas la nécessité que le paramètre de sortie soit assigné avant de sortir de la méthode"?
Il existe en fait une façon de faire cela qui est autorisée par C#. Cela renvoie à C++, et viole plutôt la belle structure orientée objet de C#.
UTILISEZ CETTE MÉTHODE AVEC PRÉCAUTION!
Voici comment vous déclarez et écrivez votre fonction avec un paramètre optionnel :
unsafe public void OptionalOutParameter(int* pOutParam = null)
{
int lInteger = 5;
// Si le paramètre est NULL, l'appelant ne se préoccupe pas de cette valeur.
if (pOutParam != null)
{
// S'il n'est pas null, l'appelant a fourni l'adresse d'un entier.
*pOutParam = lInteger; // Dé référencez le pointeur et assignez la valeur de retour.
}
}
Ensuite, appelez la fonction comme ceci :
unsafe { OptionalOutParameter(); } // ne fait rien
int MonEntier = 0;
unsafe { OptionalOutParameter(&MonEntier); } // passe en argument l'adresse de MonEntier.
Pour que cela compile, vous devrez activer le code non sécurisé dans les options du projet. Il s'agit d'une solution vraiment bricolée qui ne devrait généralement pas être utilisée, mais si pour une raison étrange, mystérieuse, inspirée par la gestion, vous avez VRAIMENT besoin d'un paramètre out optionnel en C#, alors cela vous permettra de le faire.
ICYMI: Inclus dans les nouvelles fonctionnalités de C# 7.0 énuméré ici, les "discards" sont maintenant autorisés en tant que paramètres de sortie sous la forme d'un _, pour vous permettre d'ignorer les paramètres de sortie qui ne vous intéressent pas :
p.GetCoordinates(out var x, out _); // Je me soucie seulement de x
P.S. Si vous êtes également confus avec la partie "out var x", lisez la nouvelle fonctionnalité sur les "Out Variables" sur le lien également.
Les rejets ne sont pas vraiment des variables optionnelles. C'est juste un peu de sucre syntaxique au niveau du code appelant. La fonction elle-même n'a pas connaissance qu'elle a été appelée avec un rejet.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
2 votes
Eh bien, en C++, elles ont effectivement des paramètres "out" - vous pouvez avoir un argument d'adresse initialisé à null et il est assez courant d'écrire du code de bibliothèque qui ne remplira une structure de retour que si le pointeur n'est pas nul. C'est un idiome qui remonte à l'utilisation de null pour les "arguments optionnels" dans les API C.
61 votes
@Ed et tout le monde: pourquoi cela n'aurait aucun sens? Si une fonction "retourne" une valeur via "out", je ne veux pas être obligé de l'accepter. Maintenant je sais que pour des raisons techniques le compilateur doit toujours passer quelque chose en, mais il n'y a aucune raison pour laquelle il ne pourrait pas simplement créer un local factice pour moi derrière mon dos.
6 votes
Peut-être que cela n'a pas de sens du point de vue de la façon dont les choses sont mises en œuvre ou de ce qu'est réellement un paramètre facultatif. Mais comme l'a dit romkyns, ce serait vraiment bien d'avoir des "arguments de sortie facultatifs" - interprétez cela en anglais plutôt qu'en CLR et cela devient raisonnable et, à mon avis, souhaitable.
9 votes
Le C# ne le fait pas, mais VB.NET le fait.
6 votes
Cela a été battu à mort, cependant, je ne peux m'empêcher de mentionner mon soutien pour les arguments de sortie optionnels. Je suis devenu assez habitué aux arguments optionnels par référence en définissant une valeur par défaut
null
(je viens de PHP) et en testantnull
pour procéder à la population de l'argument (pour ceux qui connaissent, pensez àpreg_match()
). Quoi qu'il en soit, bien que je comprenne d'un point de vue technique que cela soit actuellement impossible, et que PHP et C# soient plutôt incomparables, ce serait quand même un "bel" outil à avoir à disposition.0 votes
Utilisez simplement une méthode surchargée qui ne prend pas le paramètre de sortie en question, si vous en avez quelques-uns que vous voulez optionnels, cela pourrait devenir compliqué.