11
votes

Passer des objets par référence VS Valeur

Je veux juste vérifier ma compréhension des façons de gérer les choses, avant que je commence trop profondément dans la conception de mes classes. Ma compréhension actuelle est que:

  • struct est un type valeur , ce qui signifie qu'il contient réellement les éléments de données définis dans.
  • classe est un type référence , ce qui signifie qu'il contient des références aux membres de données définis dans.

  • une méthode signature passe des paramètres par valeur , ce qui signifie qu'une copie de la valeur est transmise à l'intérieur de la méthode, ce qui le rend cher pour les grandes matrices et les structures de données.

  • une signature de méthode qui définit un paramètre avec les mots-clés ref ou transmettra un paramètre par référence , ce qui signifie un pointeur à L'objet est fourni à la place.

    Ce que je ne comprends pas, c'est ce qui se passe lorsque j'invoque une méthode, ce qui se passe réellement. Est-ce que New () est invoqué? Cela vient-il de copier automatiquement les données? Ou est-ce que cela indique-t-il simplement à l'objet d'origine? Et comment utiliser ref et sur affecte cela?


2 commentaires

Demandez-vous ce qui arrive à valoriser des types ou des types de référence?


Les deux, je pense. Mais la réponse d'AVI ci-dessous semble avoir les deux cas couverts.


3 Réponses :


5
votes

Passage d'une variable de type valeur à un procédé signifie passer une copie de la variable à la méthode. Toute modification du paramètre qui a lieu à l'intérieur de la méthode n'a aucune incidence sur les données d'origine stockées dans la variable.

Si vous souhaitez que la méthode appelée modifie la valeur du paramètre, vous devez la transmettre par référence, en utilisant le mot-clé REF ou OUT.

Lorsque vous passez un paramètre de type de référence par valeur, il est possible de modifier les données pointées par la référence, telles que la valeur d'un membre de la classe. Cependant, vous ne pouvez pas modifier la valeur de la référence elle-même; C'est-à-dire que vous ne pouvez pas utiliser la même référence pour allouer la mémoire pour une nouvelle classe et l'avoir persister en dehors du bloc. Pour ce faire, passez le paramètre à l'aide du mot-clé REF (ou OUT).

Référence: Paramètres de passage (C #) < / a>


0 commentaires

13
votes

Ce que je ne comprends pas, c'est ce qui se passe lorsque j'invoque une méthode, ce qui se passe réellement. Est-ce que New () est invoqué? Cela vient-il de copier automatiquement les données? Ou est-ce que cela indique-t-il simplement à l'objet d'origine? Et comment utiliser Réf et Out affecter cela?

La réponse courte:

Le constructeur vide ne sera pas appelé automatiquement, et il ne fait que pointer simplement l'objet d'origine.
Utiliser Réf et Out n'affecte pas cela.

La réponse longue:

Je pense qu'il serait plus facile de comprendre comment c # gère les arguments de passage à une fonction.
En fait tout est adopté par valeur
vraiment ?! Tout par valeur?

Oui! Tout!

Bien sûr, il doit y avoir une sorte de différence entre les classes de passage et les objets typés simples, tels qu'un entier, sinon, ce serait une énorme performance de retour en arrière.

Eh bien. La chose est que dans les coulisses lorsque vous passez une instance de classe d'un objet à une fonction, ce qui est réellement transmis à la fonction est le pointeur de la classe. Bien sûr, le pointeur peut être transmis par valeur sans causer des problèmes de performance.

en fait, tout est adopté par la valeur; C'est juste que quand vous «passez un objet», vous transmettez en fait une référence à cela Objet (et vous passez cette référence par valeur).

Une fois que nous sommes dans la fonction, étant donné le pointeur d'argument, nous pouvons être liés à l'objet adopté par référence . < BR> Vous n'avez réellement besoin de rien faire pour cela, vous pouvez vous rapporter directement à l'instance passée comme argument (comme indiqué précédemment, tout ce processus est fait dans les coulisses).

Après avoir compris cela, Vous comprenez probablement que le constructeur vide ne sera pas appelé automatiquement, et il fait simplement pointer sur l'objet d'origine .


édité: < / p>

sur le > et ref , ils permettent aux fonctions de modifier la valeur d'un argument et de modifier ce changement persistent en dehors de la portée de la fonction. de
En un mot, l'utilisation du mot clé REF pour les types de valeur agira comme suit: xxx

va traduire en C ++ à: xxx < p> En omettant la référence, traduisez simplement: xxx

Utilisation de ces mots-clés pour Type de référence , vous permettra de réaffecter la mémoire au passage argument, et rendre la réaffectation persiste en dehors de la portée de la fonction (pour plus de détails, reportez-vous à la Page MSDN )

Note latérale:
La différence entre REF et OUT est que OUT veille à ce que la fonction appelée doit affecter une valeur à l'argument OUT, tandis que REF ne dispose pas de cette restriction, puis vous devez le gérer en attribuant une valeur par défaut vous-même, ainsi que refait la référence. La valeur initiale de l'argument est importante pour la fonction et pourrait affecter son comportement.


8 commentaires

Votre explication de Ref / Out n'est pas correcte. Tout d'abord, il n'est même pas nécessaire qu'elles soient utilisées sur des types de valeur, et deuxièmement, il n'a pas la même sémantique que de transmettre une référence par valeur. Le passage d'une référence par la valeur et une valeur par référence sont réellement différents (à la fois logiquement que fonctionnellement) et ce message démontre un manque de compréhension des concepts de base ici.


@Servy vous êtes correct, je me concentrais sur un arbre et je me suis manqué de la forêt, je suppose que je l'ai fait moins d'attention car ce n'était pas la principale question et donné un exemple de l'utilisation principale que je fais avec ou ref ... i ont mis à jour ma réponse. Pensez-vous que c'est adéquat maintenant? -


Pas vraiment. Votre explication n'explique pas vraiment beaucoup. Si l'OP ne comprend pas déjà C ++, l'exemple ne vous aide pas, et la possibilité de réaffecter un type de référence est une chose que vous pouvez faire, mais ce n'est pas une explication de ce qui passe par référence signifie .


@Servy à ce stade, nous sommes en désaccord. La question a été entièrement répondue et le but de la sortie et de la référence est expliqué. L'exemple est un bonus juste -il ne fait aucun mal, et il existe un lien pour une explication plus détaillée. Toute façon, merci de vos commentaires. Je ferai un effort pour être plus précis dans le premier coup dans les réponses futures.


@Avitaturner Votre compréhension de Ref est imparfaite. C # fait fonction appropriée par référence lorsque vous utilisez le modificateur REF sur les paramètres.


@Talhasayed Vous avez tort. Ce qui est passé est un "pointeur au pointeur" qui est une adresse. En bas, c'est un nombre qui est passé par la valeur. L'adresse est en train d'être la dupliquée sur la pile, par conséquent, en passant par la valeur. Cela se traduit par une passe par référence à l'instance de l'objet (ou comme j'ai écrit dans ma réponse ce qui est réellement transmis à la fonction est le pointeur ) mais jamais le moins, l'appel est utilisé avec un appel par valeur de l'adresse.


@Aviturner Oui, c'est exactement ce que je comprends aussi. Alors, n'est-ce pas appelé passant par référence? Depuis l'utilisation du paramètre Réf, il ajoute implicitement un autre niveau d'indirection et passe un pointeur à un pointeur. Je sais à la fin de la journée, une valeur est passée, mais comme comme un pointeur à un pointeur qui est adopté implicitement, ce concept n'est-il pas appelé "passe par référence". Sinon, ce que l'on s'appelle passer par référence?


@Talhasayed Oui, c'est "passe par référence". Il serait peut-être très facile de la saisir une fois que vous connaissez déjà le concept, mais que vous vous en souvenez, le PO n'a pas vos connaissances antérieures, sinon il ne poserait pas la question. Dans le message, j'utilise une tactique explicative qui comprend ce qui se passe au fond, qui transmet une adresse par valeur. Il semble que la tactique a fonctionné, le PO était satisfait de l'explication.



0
votes

Tragiquement, il n'y a aucun moyen de passer un objet par valeur en C # ou VB.NET. Je suggère plutôt que vous passez, par exemple, nouvelle classe1 (objet1) où Object1 est une instance de classe1. Vous devrez écrire votre propre nouvelle méthode pour le faire, mais au moins vous avez ensuite une capacité facile passe-valeur pour la classe1.


0 commentaires