109 votes

Quand utiliser la ref et quand il n'est pas nécessaire en C#

J'ai un objet qui est de mon état de la mémoire du programme et aussi quelques autres travailleurs fonctions que j'ai passer l'objet à modifier l'état. J'ai été en passant par la réf pour le travailleur fonctions. Cependant je suis tombé sur la fonction suivante.

byte[] received_s = new byte[2048];
IPEndPoint tmpIpEndPoint = new IPEndPoint(IPAddress.Any, UdpPort_msg);
EndPoint remoteEP = (tmpIpEndPoint);

int sz = soUdp_msg.ReceiveFrom(received_s, ref remoteEP);

Il me confond, car les deux received_s et remoteEP sont de retour stuff de la fonction. Pourquoi est - remoteEP besoin d'un ref et received_s ne l'est pas?

Je suis aussi un programmeur en c, donc je vais avoir un problème pour faire des pointeurs de ma tête.

Edit: On dirait que les objets en C# sont des pointeurs à l'objet sous le capot. Ainsi, lorsque vous passez un objet à une fonction que vous pouvez ensuite modifier l'objet contenu via le pointeur et la seule chose passé à la fonction est le pointeur vers l'objet et l'objet lui-même n'est pas copié. Vous utilisez ref ou si vous voulez être en mesure de changer ou de créer un nouvel objet dans la fonction qui est comme un double pointeur.

231voto

Jon Skeet Points 692016

Réponse courte: lire mon article sur l'argument de passage.

Réponse longue: lorsqu'une référence de type de paramètre est passé par valeur, seule la référence est passée, pas une copie de l'objet. C'est comme passer un pointeur (en valeur) en C ou C++. Les changements à la valeur du paramètre lui-même ne pas être vus par l'appelant, mais des changements dans l'objet qui points de référence va être vu.

Lorsqu'un paramètre (de tout type) est passé par référence, ce qui signifie que toute modification du paramètre sont vus par l'appelant - les modifications apportées au paramètre sont les changements de la variable.

L'article explique tout cela plus en détail, bien sûr :)

Réponse utile: vous presque jamais besoin d'utiliser ref/out. C'est essentiellement un moyen d'en obtenir une autre valeur de retour, et doit généralement être évitée, précisément parce qu'elle signifie que la méthode est probablement essayer d'en faire trop. Ce n'est pas toujours le cas (TryParse etc sont les exemples canoniques de l'utilisation raisonnable de l' out), mais à l'aide de ref/devrait être d'une rareté relative.

27voto

Michael Meadows Points 15277

Pensez à un non-réf paramètre comme étant un pointeur, et un paramètre de référence comme un double pointeur. Cela m'a aidé le plus.

Vous devriez presque jamais de transmettre des valeurs par ref. Je pense que si ce n'était pas pour l'interopérabilité des préoccupations, l' .Net de l'équipe n'aurait jamais inclus dans la spécification d'origine. Le OO façon de traiter avec le plus de problème que les paramètres de ref résoudre est:

Pour plusieurs valeurs de retour

  • Créer des structures qui représentent les multiples valeurs de retour

Pour les primitives que le changement dans une méthode comme le résultat de l'appel de méthode (méthode a des effets secondaires sur la primitive de paramètres)

  • Mettre en œuvre la méthode dans un objet comme une méthode d'instance et de manipuler l'état de l'objet (pas de paramètres) dans le cadre de l'appel de la méthode
  • Utiliser le multiple de la valeur de retour de la solution et de fusionner les valeurs de retour à votre état
  • Créer un objet qui contient de l'état qui peuvent être manipulées par une méthode et de l'objet en tant que paramètre, et non pas les primitifs eux-mêmes.

12voto

Chris Points 3290

Vous pourriez probablement écrire toute une application en C# et ne jamais passer les objets/les structures par ref.

J'ai eu un professeur qui m'a dit ceci:

Le seul endroit que vous souhaitez utiliser refs est l'endroit où vous soit 1. Souhaitez passer un objet de grande taille (c'est à dire, les objets/struct a des objets/les structures à l'intérieur à plusieurs niveaux) et de la copie qu'il serait coûteux et 2. Vous appelez un Cadre, de l'API Windows ou d'autres API qui en a besoin.

Ne pas le faire juste parce que vous le pouvez. Vous pouvez obtenir des bit dans le cul par de méchants bugs si vous commencez à changer les valeurs des param et ne faites pas attention.

Je suis d'accord avec ses conseils, et mes cinq ans plus depuis l'école, je n'ai jamais eu besoin pour cela de l'extérieur de l'appel de la structure ou de l'API Windows.

3voto

Brian Points 14040

Pensez à une ref en ce sens vous êtes de passage d'un pointeur par référence. N'utilisez pas une ref signifie que vous êtes en passant un pointeur en valeur.

Mieux encore, ignorer ce que je viens de dire (c'est sans doute trompeur, surtout avec les types de valeur) et la lecture de Cette page MSDN.

3voto

Chris Hynes Points 5110

Depuis received_s est un tableau, vous êtes en passant un pointeur vers ce tableau. La fonction manipule que les données existantes en place, en ne changeant pas le sous-jacent ou d'emplacement du pointeur. Le mot-clé ref signifie que vous êtes de passage le réel pointeur à l'endroit et de mettre à jour le pointeur à l'extérieur de la fonction, de sorte que la valeur à l'extérieur de la fonction de changement.

E. g. le tableau d'octets est un pointeur vers la mémoire avant et après, la mémoire vient d'être mis à jour.

Le point de Terminaison de référence est en fait mise à jour le pointeur vers le point de Terminaison à l'extérieur de la fonction pour une nouvelle instance générée à l'intérieur de la fonction.

Prograide.com

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.

Powered by:

X