Si nous voulons obtenir une valeur d'une méthode, nous pouvons utiliser l'une ou l'autre des valeurs de retour, comme ceci:
public int GetValue();
ou:
public void GetValue(out int x);
Je ne comprends pas vraiment les différences entre eux, donc je ne sais pas ce qui est le mieux. Pouvez-vous m'expliquer cela?
Je vous remercie.
Tuple
si vous le souhaitez, mais le consensus général est que si vous avez besoin de renvoyer plus d'une chose, les choses sont généralement liées d'une manière ou d'une autre et cette relation est généralement mieux exprimée en tant que classe.return Tuple.Create(x, y, z);
N'est-ce pas moche. De plus, il est tard dans la journée de les faire introduire au niveau de la langue. La raison pour laquelle je ne créerais pas de classe pour renvoyer les valeurs d'un paramètre ref / out est que les paramètres ref / out n'ont vraiment de sens que pour les grandes structures mutables (comme les matrices) ou les valeurs facultatives, et ce dernier est discutable.Tuple<>
et C # tuples !. Je souhaitais juste que C # autorise le retour de types anonymes à partir de méthodes avec un type d'inférence de compilateur (commeauto
dans Dlang).Réponses:
Les valeurs de retour sont presque toujours le bon choix lorsque la méthode n'a rien d'autre à renvoyer. (En fait, je ne peux pas penser à tous les cas où je serais jamais veux une méthode vide avec un
out
paramètre, si j'avais le choix. C # 7 deDeconstruct
méthodes de déconstruction du langage soutenu agit comme une exception très, très rare à cette règle .)Mis à part toute autre chose, cela empêche l'appelant d'avoir à déclarer la variable séparément:
contre
Les valeurs de sortie empêchent également le chaînage de méthodes comme ceci:
(En effet, c'est aussi l'un des problèmes avec les setters de propriété, et c'est pourquoi le modèle de générateur utilise des méthodes qui retournent le générateur, par exemple
myStringBuilder.Append(xxx).Append(yyy)
.)De plus, les paramètres de sortie sont légèrement plus difficiles à utiliser avec la réflexion et rendent généralement les tests plus difficiles. (Plus d'efforts sont généralement déployés pour faciliter la simulation des valeurs de retour que des paramètres out). Fondamentalement, je ne peux penser à rien de ce qu'ils font facilitent ...
Renvoie les valeurs FTW.
EDIT: En termes de ce qui se passe ...
Fondamentalement, lorsque vous passez un argument pour un paramètre "out", vous devez passer une variable. (Les éléments du tableau sont également classés comme des variables.) La méthode que vous appelez n'a pas de "nouvelle" variable sur sa pile pour le paramètre - elle utilise votre variable pour le stockage. Toute modification de la variable est immédiatement visible. Voici un exemple montrant la différence:
Résultats:
La différence se situe à l'étape «post» - c'est-à-dire après que la variable locale ou le paramètre a été modifié. Dans le test ReturnValue, cela ne fait aucune différence pour la
value
variable statique . Dans le test OutParameter, lavalue
variable est modifiée par la lignetmp = 10;
la source
Dictionary.TryGetValue
n'est pas applicable ici, car ce n'est pas une méthode vide. Pouvez-vous expliquer pourquoi vous voudriez unout
paramètre au lieu d'une valeur de retour? (Même pourTryGetValue
, je préfère une valeur de retour qui contient toutes les informations de sortie, personnellement. Voir NodaTimeParseResult<T>
pour un exemple de la façon dont je l'aurais conçu.)out
paramètre, vous ne pouvez tout simplement rien faire avec la valeur.Ce qui est mieux, dépend de votre situation particulière. L'une des raisons
out
existe est de faciliter le retour de plusieurs valeurs à partir d'un appel de méthode:Donc l'un n'est pas par définition meilleur que l'autre. Mais généralement, vous voudrez utiliser un simple retour, sauf si vous avez la situation ci-dessus par exemple.
EDIT: Ceci est un exemple montrant l'une des raisons pour lesquelles le mot-clé existe. Ce qui précède ne doit en aucun cas être considéré comme une bonne pratique.
la source
Vous devriez généralement préférer une valeur de retour à un paramètre de sortie. Les paramètres de sortie sont un mal nécessaire si vous vous retrouvez à écrire du code qui doit faire 2 choses. Un bon exemple de ceci est le modèle Try (tel que Int32.TryParse).
Considérons ce que l'appelant de vos deux méthodes devrait faire. Pour le premier exemple, je peux écrire ceci ...
Notez que je peux déclarer une variable et l'affecter via votre méthode en une seule ligne. Pour le 2ème exemple, cela ressemble à ceci ...
Je suis maintenant obligé de déclarer ma variable à l'avance et d'écrire mon code sur deux lignes.
mettre à jour
Les directives de conception du .NET Framework constituent un bon endroit pour poser ces types de questions. Si vous avez la version du livre, vous pouvez voir les annotations d'Anders Hejlsberg et d'autres sur ce sujet (pages 184-185) mais la version en ligne est ici ...
http://msdn.microsoft.com/en-us/library/ms182131(VS.80).aspx
Si vous avez besoin de renvoyer deux choses à partir d'une API, les encapsuler dans une structure / classe serait mieux qu'un paramètre out.
la source
Il y a une raison d'utiliser un
out
paramètre qui n'a pas déjà été mentionné: la méthode appelante est obligée de le recevoir. Si votre méthode produit une valeur que l'appelant ne doit pas ignorer, en faire unout
oblige l'appelant à l'accepter spécifiquement:Bien sûr, l'appelant peut toujours ignorer la valeur d'un
out
paramètre, mais vous avez attiré son attention dessus.C'est un besoin rare; le plus souvent, vous devriez utiliser une exception pour un problème réel ou renvoyer un objet avec des informations d'état pour un "FYI", mais il peut y avoir des circonstances où cela est important.
la source
C'est la préférence principalement
Je préfère les retours et si vous avez plusieurs retours, vous pouvez les envelopper dans un résultat DTO
la source
Vous ne pouvez avoir qu'une seule valeur de retour alors que vous pouvez avoir plusieurs paramètres de sortie.
Il vous suffit de prendre en compte les paramètres dans ces cas.
Cependant, si vous devez renvoyer plus d'un paramètre à partir de votre méthode, vous voudrez probablement regarder ce que vous retournez d'une approche OO et déterminer s'il vaut mieux retourner un objet ou une structure avec ces paramètres. Par conséquent, vous êtes de nouveau à une valeur de retour.
la source
Vous devez presque toujours utiliser une valeur de retour. '
out
' Les paramètres créent un peu de friction avec beaucoup d'API, de compositionnalité, etc.L'exception la plus notable qui me vient à l'esprit est lorsque vous souhaitez renvoyer plusieurs valeurs (.Net Framework n'a pas de tuples jusqu'à 4.0), comme avec le
TryParse
modèle.la source
Je préférerais ce qui suit au lieu de l'un ou l'autre de ceux de cet exemple simple.
Mais, ils sont tous très similaires. Habituellement, on n'utiliserait «out» que s'il avait besoin de renvoyer plusieurs valeurs de la méthode. Si vous voulez envoyer une valeur dans et hors de la méthode, vous choisirez «ref». Ma méthode est la meilleure, si vous ne renvoyez qu'une valeur, mais si vous voulez passer un paramètre et récupérer une valeur, vous choisirez probablement votre premier choix.
la source
Je pense que l'un des rares scénarios où cela serait utile serait lorsque vous travaillez avec de la mémoire non managée, et vous voulez faire comprendre que la valeur "retournée" doit être supprimée manuellement, plutôt que de s'attendre à ce qu'elle soit supprimée seule .
la source
En outre, les valeurs de retour sont compatibles avec les paradigmes de conception asynchrones.
Vous ne pouvez pas désigner une fonction "async" si elle utilise des paramètres ref ou out.
En résumé, les valeurs de retour permettent le chaînage de méthodes, une syntaxe plus claire (en éliminant la nécessité pour l'appelant de déclarer des variables supplémentaires) et permettent des conceptions asynchrones sans nécessiter de modification substantielle dans le futur.
la source
Les deux ont un but différent et ne sont pas traités de la même manière par le compilateur. Si votre méthode doit renvoyer une valeur, vous devez utiliser return. Out est utilisé lorsque votre méthode doit renvoyer plusieurs valeurs.
Si vous utilisez return, les données sont d'abord écrites dans la pile de méthodes, puis dans la méthode appelante. En cas de out, il est directement écrit dans la pile des méthodes appelantes. Je ne sais pas s'il y a d'autres différences.
la source
Comme d'autres l'ont dit: valeur de retour, pas de param.
Puis-je vous recommander le livre "Framework Design Guidelines" (2e éd)? Les pages 184-185 couvrent les raisons d'éviter les paramètres. L'ensemble du livre vous guidera dans la bonne direction sur toutes sortes de problèmes de codage .NET.
L'utilisation de l'outil d'analyse statique, FxCop, est alliée aux directives de conception de cadre. Vous le trouverez sur les sites de Microsoft en téléchargement gratuit. Exécutez ceci sur votre code compilé et voyez ce qu'il dit. S'il se plaint de centaines et de centaines de choses ... pas de panique! Regardez calmement et attentivement ce qu'il dit sur chaque cas. Ne vous précipitez pas pour réparer les choses dès que possible. Apprenez de ce qu'il vous dit. Vous serez mis sur la voie de la maîtrise.
la source
L'utilisation du mot-clé out avec un type de retour booléen peut parfois réduire le gonflement du code et augmenter la lisibilité. (Principalement lorsque les informations supplémentaires dans le paramètre out sont souvent ignorées.) Par exemple:
contre:
la source
Il n'y a pas de réelle différence. Les paramètres de sortie sont en C # pour permettre à la méthode de renvoyer plus d'une valeur, c'est tout.
Cependant, il existe de légères différences, mais aucune d'entre elles n'est vraiment importante:
L'utilisation du paramètre out vous obligera à utiliser deux lignes comme:
tout en utilisant la valeur de retour vous permettra de le faire en une seule ligne:
Une autre différence (à corriger uniquement pour les types valeur et uniquement si C # n'inline pas la fonction) est que l'utilisation de la valeur de retour fera nécessairement une copie de la valeur lorsque la fonction retourne, tandis que l'utilisation du paramètre OUT ne le fera pas nécessairement.
la source
out est plus utile lorsque vous essayez de renvoyer un objet que vous déclarez dans la méthode.
Exemple
la source
valeur de retour est la valeur normale renvoyée par votre méthode.
Où comme paramètre out , well out et ref sont 2 mots clés de C # ils permettent de passer des variables comme référence .
La grande différence entre ref et out est que ref doit être initialisé avant et out pas
la source
Je suppose que je ne vais pas me renseigner sur cette question, mais je suis très programmeur expérimenté, et j'espère que certains des lecteurs les plus ouverts d'esprit y prêteront attention.
Je pense que cela convient mieux aux langages de programmation orientés objet que leurs procédures de retour de valeur (VRP) soient déterministes et pures.
«VRP» est le nom académique moderne d'une fonction appelée dans le cadre d'une expression, et a une valeur de retour qui remplace théoriquement l'appel lors de l'évaluation de l'expression. Par exemple, dans une instruction telle que
x = 1 + f(y)
la fonctionf
sert de VRP.«Déterministe» signifie que le résultat de la fonction dépend uniquement des valeurs de ses paramètres. Si vous l'appelez à nouveau avec les mêmes valeurs de paramètres, vous êtes certain d'obtenir le même résultat.
«Pure» signifie pas d'effets secondaires: l'appel de la fonction ne fait rien d'autre que calculer le résultat. Cela peut être interprété comme ne signifiant aucun effet secondaire important , en pratique, donc si le VRP sort un message de débogage à chaque fois qu'il est appelé, par exemple, cela peut probablement être ignoré.
Ainsi, si, en C #, votre fonction n'est pas déterministe et pure, je dis que vous devriez en faire une
void
fonction (en d'autres termes, pas un VRP), et toute valeur qu'elle doit retourner doit être retournée dans unout
ou unref
paramètre.Par exemple, si vous avez une fonction pour supprimer certaines lignes d'une table de base de données et que vous voulez qu'elle renvoie le nombre de lignes qu'elle a supprimées, vous devez la déclarer comme ceci:
public void DeleteBasketItems(BasketItemCategory category, out int count);
Si vous souhaitez parfois appeler cette fonction sans obtenir le
count
, vous pouvez toujours déclarer une surcharge.Vous voudrez peut-être savoir pourquoi ce style convient mieux à la programmation orientée objet. En gros, il s'inscrit dans un style de programmation qui pourrait être (un peu imprécisément) appelé «programmation procédurale», et c'est un style de programmation procédurale qui convient mieux à la programmation orientée objet.
Pourquoi? Le modèle classique des objets est qu'ils ont des propriétés (aka attributs), et vous interrogez et manipulez l'objet (principalement) en lisant et en mettant à jour ces propriétés. Un style de programmation procédurale a tendance à faciliter cette tâche, car vous pouvez exécuter du code arbitraire entre les opérations qui obtiennent et définissent des propriétés.
L'inconvénient de la programmation procédurale est que, parce que vous pouvez exécuter du code arbitraire partout, vous pouvez obtenir des interactions très obtuses et vulnérables aux bogues via des variables globales et des effets secondaires.
Donc, tout simplement, il est bon de signaler à quelqu'un qui lit votre code qu'une fonction pourrait avoir des effets secondaires en la rendant sans valeur.
la source
_
symbole de suppression pour ignorer un paramètre out, par exemple: DeleteBasketItems (category, out _);