J'ai un objet qui est mon état en mémoire du programme et j'ai également d'autres fonctions de travail auxquelles je passe l'objet pour modifier l'état. Je l'ai passé par référence aux fonctions de travail. 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);
Cela me déroute parce que les deux received_s
et remoteEP
retournent des trucs de la fonction. Pourquoi a-t-il remoteEP
besoin d'un ref
et received_s
non?
Je suis également programmeur ac donc j'ai du mal à sortir les pointeurs de ma tête.
Edit: On dirait que les objets en C # sont des pointeurs vers l'objet sous le capot. Ainsi, lorsque vous passez un objet à une fonction, vous pouvez alors modifier le contenu de l'objet via le pointeur et la seule chose passée à la fonction est le pointeur vers l'objet afin que l'objet lui-même ne soit pas copié. Vous utilisez ref ou out si vous voulez pouvoir basculer ou créer un nouvel objet dans la fonction qui est comme un double pointeur.
if (int.TryParse(text, out int value)) { ... use value here ... }
Pensez à un paramètre non-ref comme étant un pointeur et à un paramètre ref comme un double pointeur. Cela m'a le plus aidé.
Vous ne devriez presque jamais passer de valeurs par réf. Je soupçonne que si ce n'était pas pour des questions d'interopérabilité, l'équipe .Net ne l'aurait jamais inclus dans la spécification d'origine. La manière OO de traiter la plupart des problèmes que les paramètres ref résolvent est de:
Pour plusieurs valeurs de retour
Pour les primitives qui changent dans une méthode à la suite de l'appel de méthode (la méthode a des effets secondaires sur les paramètres primitifs)
la source
IPAddress.TryParse(string, out IPAddress)
.if (int.TryParse("123", out var theInt) { /* use theInt */ }
nous, il y avaitvar candidate = int.TrialParse("123"); if (candidate.Parsed) { /* do something with candidate.Value */ }
plus de code, mais c'est beaucoup plus cohérent avec la conception du langage C #.Vous pourriez probablement écrire une application C # entière et ne jamais transmettre d'objets / structures par ref.
J'ai eu un professeur qui m'a dit ceci:
Je suis d'accord avec ses conseils, et au cours de mes cinq années et plus depuis l'école, je n'en ai jamais eu besoin en dehors d'appeler le Framework ou l'API Windows.
la source
SetName(person, "John Doe")
, la propriété name changera et ce changement sera répercuté sur l'appelant.Puisque receive_s est un tableau, vous passez un pointeur vers ce tableau. La fonction manipule ces données existantes en place, sans modifier l'emplacement ou le pointeur sous-jacent. Le mot-clé ref signifie que vous passez le pointeur réel vers l'emplacement et que vous mettez à jour ce pointeur dans la fonction extérieure, de sorte que la valeur de la fonction extérieure change.
Par exemple, le tableau d'octets est un pointeur vers la même mémoire avant et après, la mémoire vient d'être mise à jour.
La référence Endpoint met en fait à jour le pointeur vers Endpoint dans la fonction extérieure vers une nouvelle instance générée à l'intérieur de la fonction.
la source
Pensez à une référence comme signifiant que vous passez un pointeur par référence. Ne pas utiliser de référence signifie que vous passez un pointeur par valeur.
Mieux encore, ignorez ce que je viens de dire (c'est probablement trompeur, en particulier avec les types de valeur) et lisez cette page MSDN .
la source
ma compréhension est que tous les objets dérivés de la classe Object sont passés en tant que pointeurs alors que les types ordinaires (int, struct) ne sont pas passés en tant que pointeurs et nécessitent une référence. Je ne suis ni sûr de la chaîne (est-elle finalement dérivée de la classe Object?)
la source
Bien que je sois d'accord avec la réponse de Jon Skeet dans l'ensemble et certaines des autres réponses, il existe un cas d'utilisation pour l'utilisation
ref
, et c'est pour renforcer les optimisations des performances. Lors du profilage des performances, il a été observé que la définition de la valeur de retour d'une méthode a de légères implications sur les performances, tandis que l'utilisationref
comme argument par lequel la valeur de retour est renseignée dans ce paramètre entraîne la suppression de ce léger goulot d'étranglement.Cela n'est vraiment utile que lorsque les efforts d'optimisation sont poussés à des niveaux extrêmes, sacrifiant la lisibilité et peut-être la testabilité et la maintenabilité pour gagner des millisecondes ou peut-être des millisecondes fractionnées.
la source
Règle de base zéro d'abord, les primitives sont passées par valeur (pile) et non primitives par référence (tas) dans le contexte des TYPES impliqués.
Les paramètres impliqués sont transmis par valeur par défaut. Bon article qui explique les choses en détail. http://yoda.arachsys.com/csharp/parameters.html
Nous pouvons dire (avec avertissement) que les types non primitifs ne sont rien d'autre que des pointeurs Et quand nous les passons par ref, nous pouvons dire que nous passons Double Pointer
la source