9
votes

Utilisation des mots-clés de Ref & Out avec le passage par référence et en passant par la valeur en C #

Voici ce que je comprends jusqu'à présent:

Pass par valeur

Passage par valeur signifie qu'une copie d'un argument est passée. Les modifications apportées à cette copie ne changent pas l'original.

Pass par référence

Passage par référence signifie une référence à l'original est passé. Les modifications apportées à la référence affectent l'original.

Mot-clé Ref

Ref indique au compilateur que l'objet est initialisé avant d'entrer dans la fonction. Réf signifie que la valeur est déjà définie, la méthode peut donc la lire et la modifier. Ref est de deux manières, à la fois de l'intérieur et de l'extérieur.

Mot clé

Out indique au compilateur que l'objet sera supposé dans la fonction. Out signifie que la valeur n'est pas déjà définie et doit donc être définie avant d'appeler le retour. Out n'est qu'un moyen, ce qui est sorti.

Question

Donc, dans quels scénarios alloueriez-vous l'utilisation des mots-clés Ref et Out, en passant par référence ou en passant par la valeur? Des exemples aideraient énormément.

aide grandement appréciée.


5 commentaires

Je ne comprends pas entièrement votre question ... Vous ne pouvez pas utiliser les deux ref et out sur le même argument. Et ces deux mots clés sont utilisés pour passer par référence.


Je pense que vous êtes mal compris que "passer par référence" et "transmettre des références par valeur"


Le mot clé ref n'est utile que sur des valeurs par défaut de valeur, telles que des structures, des INT, des flotteurs, des bools et des énumérums.


ELLZ, vous peut transmettre une référence par référence et il y a une utilisation pour cela.


wow .. en fait je ne savais pas ça .. lol


7 Réponses :


20
votes

Vous seriez JAMAIS FORT> Combinez Réf code> et out code> sur 1 paramètre. Ils signifient tous les deux «passer par référence».

Vous pouvez bien sûr combiner les paramètres de référence et les paramètres d'une méthode. P>

la différence entre ref code> et out code> est principalement dans intention forte>. Ref signale le transport de données à 2 voies, désintègre un passage. P>

mais en plus de l'intention, le compilateur C # piste définitive-assignation et qui fait la différence la plus notable. Il empêche également l'utilisation abusive (lecture) d'un paramètre OUT. P>

void SetOne(out int x) 
{
  int y = x + 1; // error, 'x' not definitely assigned.
  x = 1;         // mandatory to assign something
}

void AddTwo(ref int x)
{
    x = x + 2;  // OK, x  is known to be assigned
}

void Main()
{
    int foo, bar;

    SetOne(out foo); // OK, foo does not have to be assigned
    AddTwo(ref foo); // OK, foo assigned by SetOne
    AddTwo(ref bar); // error, bar is unassigned
}


2 commentaires

Ray, dans mes exemples addtwo (out foo) modifiera foo . C'est la partie par référence. Comment cela fonctionne-t-il est dépendant de la mise en œuvre, mais il sera généralement le même pour Ref et Out. Et probablement des compensations empilées au lieu des pointeurs.


Je suis désolé. Oui, il y avait un bogue dans mon code de test. Après le corriger, j'ai vu que les paramètres «sortis» ne sont pas passés à l'exception, mais sont passés à la FAE par référence avec la contrainte supplémentaire de la mission définitive. Veuillez accepter mes excuses.



0
votes

Vous passez en référence quelque chose que vous souhaitez être lus et écrit par une autre fonction, vous devez donc passer la variable initialisée afin d'être correctement lu.

EDIT: Exemple: P>

void mymethod2(out string a) {
  a="hello";
}


0 commentaires

1
votes

EDIT: strong> J'ai corrigé cette réponse pour refléter que le mot-clé «OUT» en C # ne fait pas ce à quoi vous pourriez vous attendre (par exemple, un paramètre triciel de sortie dans le sens de la science informatique du terme ). J'indiquais à l'origine que "Out" était de la valeur, mais a été prouvé faux.

Vous ne pouvez pas utiliser "OUT" et "REF 'ensemble. Il y a trois conventions d'appel dans C # (Cadre NET): P>

  • pas de mots clés = passer par valeur (dans) li>
  • 'OUT' Mots-clés = Pass par référence (REF) sans condition d'affectation définitive avant d'appeler li>
  • 'ref' mot-clé = passer par référence (REF) avec une condition d'affectation définie avant appeler li> ul>

    c # n'a pas de capacité de paramètre tricielle ou hors de sortie. p>

    Pour voir que les paramètres "OUT" en C # ne sont pas true Paramètres, vous pouvez utiliser le code suivant: P>

    Passing by value
    Initial
    Initial
    Passing by reference with 'out' keyword
    Initial
    OUT
    Passing by reference with 'ref' keyword
    OUT
    REF
    


9 commentaires

out est pas en valeur.


Cela dépend de ce que vous lisez le manuel d'informatique que vous lisez, mais la plupart envisagent de tous les exemples de "Pass par valeur". Le concept essentiel de passage par valeur est que lorsqu'il est passé, vous copiez la valeur au lieu d'un pointeur. BTW, il y a cinq schémas de passage de paramètres reconnus dans tous les suivants: IN, OUT, IN-OUT, REF et NAME. C # seulement a dans, out et réf. Le passage par nom est très intéressant. Recherchez Algol-68 si vous êtes curieux.


J'ai oublié que de nombreuses langues de retour en arrière peuvent également transmettre par référence. Cela fait une différence lorsqu'ils retournent plusieurs fois, par exemple avec un appel d'appel / cc ou une langue contenant de vrais générateurs.


Mes excuses. J'étais incorrecte à propos de l'utilisation C # du mot clé "OUT". Comme Mehrdad, Henk, et d'autres, cela n'a pas dit, il ne crée pas de paramètre de sortie, mais un paramètre Réforateur avec une contrainte supplémentaire sur une affectation définitive. Désolé pour la confusion. Mon premier commentaire est précis, cependant. Je vais éditer ma réponse pour éviter toute confusion future.


Pas de soucis; Il est facile d'obtenir ce genre de choses confus. Juste pour être clair, à la fois sur et réfléchir, imposer des exigences d'affectation définitives. (1) Sur le côté de l'appelant (1a) Les variables REF doivent être définitivement attribuées avant que les variables de l'appel (1b) ne doivent pas nécessairement être attribuées avant que les variables d'appel, (1c) des variables sont datés après l'appel. (2) Sur le côté de la calle, (2a) les variables REF sont da tout au long, (2b) des variables de sortie ne sont pas-da lors de l'entrée, et (2C) des variables doivent être da avant chaque retour normal.


Oui, mon texte était trompeur. J'ai bien compris cette partie de cela, mais la façon dont j'ai dit que ce n'était pas clair. J'ai corrigé mon verbiage.


Pour distinguer les références C # / COM-Style de votre entrée / sortie / in-Out / Ref, ce que je fais habituellement est que je dis "copie-out" ou "copie en copie-copie" lorsque vous diriez simplement " sortir "ou" in-out ".


De plus, je remarque qu'il existe d'autres mécanismes de passage des paramètres autres que vos cinq. Evaluation pass-by-paresseux, par exemple, vient immédiatement à l'esprit. (Et je suis d'accord, le passe-nom d'Algol 68 est un peu bizarre.)


@Rayburns: est "Readonly-ref" non considéré comme distinct de "REF '(quand il existe)? Tandis que les types de valeur .NET sont rarement très gros, il existe de nombreux cas où la bonne façon de passer de grandes valeurs serait «Readonly-ref '(transmettre des valeurs immuables par« Readonly-Ref »devrait être autorisée, mais les transmettre par' ref ' ne devrait pas; permettre une valeur immuable d'être "passée par" REF '"mais les copier en premier, comme cela est fait avec des méthodes d'instance de type valeur dans les langues .NET, est le mal).



0
votes

Utilisation du mot clé est utile si vous avez une méthode que vous devez renvoyer plusieurs valeur. Par exemple, consultez des méthodes telles que int.tryparse () .

Utilisation de ref est plus pour explicite des objets. Gardant à l'esprit que toute non primitive passée dans une méthode est intrinsèquement passée par référence, il n'y a pas beaucoup de besoin de celui-ci dans le code géré normal. En déclarant le mot-clé ref, vous indiquez que le paramètre sera probablement modifié dans le corps de la méthode et que le code d'appel doit donc en être conscient (pourquoi vous devez donc ajouter explicitement le ref dans le code d'appel aussi.


0 commentaires

1
votes

Vous comprenez la dynamique de transmettre de toute façon. Certains scénarios de paramètres peuvent être:

  • REF INT NUM Pour un paramètre IN / OUT. La fonction peut modifier la valeur dedans.
  • out INT NUM Comme Réfermer la fonction doit affecter une valeur à son retour.

    dans les paramètres de sortie généraux sont bons pour le moment où une fonction doit renvoyer plusieurs valeurs, car une fonction n'a qu'une valeur de retour (bien qu'elle puisse être composée).

    Parfois, les fournisseurs d'accès à des données, comme certaines méthodes ADO.NET, utilisez des paramètres de sortie pour obtenir des informations en arrière. Certaines méthodes d'accès aux données Mimic Base de données stockées des procédures contenant des paramètres d'entrée / sortie.

    EDIT: Une stipulation pour les types de référence est les paramètres ref StringBuilder mot ou stringbuilder mot (par valeur) se comporter de la même manière - la chaîne L'extérieur est affecté, bien que l'implémentation sous-jacente puisse différer légèrement, car à ce stade, la mise au point est la référence et non la valeur sur le tas.


1 commentaires

Facilement la meilleure et la meilleure réponse directe de tous ces temps.



0
votes

Si vous comprenez C ++ peut-être que cela vous aidera:

void Foo(Bar) {} // pass by value c# (if it's a value type ;))
void Foo(Bar) {} // c++

void Foo(Bar) {} // pass by reference c# (if it's a reference type ;))
void Foo(Bar&) {} // c++

void Foo(ref Bar) {} // c#
void Foo(Bar*) // c++

void Foo(out Bar) {} // c#
void Foo(Bar**) {} // c++ (the contents of *Bar needs to be filled up)


0 commentaires

8
votes

Aide très appréciée p>

Votre compréhension sera améliorée par une utilisation correcte et minutieuse de la langue. P>

En passant par la valeur des moyens de copie d'un argument est passé. p> Blockquote>

Oui, cela est tout à fait exact. P>

Les modifications apportées à cette copie ne changent pas l'original. P> Blockquote>

Pas exactement. Commencez par distinguer soigneusement entre valeurs em> et Variables em>. Considérez: p>

class Foo { public int x; }
...
void N() 
{
  Foo blah = new Foo();
  blah.x = 0;
  M(blah);
}
...
void M(Foo foo)
{
  foo.x = 123; // changes blah.x
  foo = null; // does not change blah
}


0 commentaires