8
votes

Sont REF et OUT dans C # les mêmes un indicateur de C ++?

Je viens de faire une routine d'échange en C # comme ceci: xxx pré>

Il fait la même chose que ce code C ++ fait: P>

void swap(int *d1, int *d2)
{
    int temp=*d1;
    *d1=*d2;
    *d2=temp;
}


0 commentaires

7 Réponses :


6
votes

Les paramètres de référence en C # peuvent être utilisés pour remplacer un utilisation des pointeurs, oui. Mais pas tous.

Un autre usage courant pour les pointeurs est un moyen de itération sur une matrice. Les paramètres OUT / REF ne peuvent pas faire cela, donc non, ils ne sont pas «identiques que des pointeurs».


0 commentaires

10
votes

Ils sont plus limités. Vous pouvez dire ++ sur un pointeur, mais pas sur un ref ou out .

EDIT DE CONFUSION DANS LES COMMENTAIRES Donc, pour être absolument clair: le point ici est de comparer avec les capacités des pointeurs. Vous ne pouvez pas effectuer la même opération que PTR ++ sur un ref / out , c'est-à-dire adresser un emplacement adjacent en mémoire. C'est vrai (mais non pertinent ici) que vous pouvez effectuer l'équivalent de (* PTR) ++ , mais ce serait le comparer aux capacités des valeurs , pas les pointeurs .


C'est un pari sûr qu'ils sont seuls juste des pointeurs, car la pile ne se déplace pas et que c # est soigneusement organisé, de sorte que ref et se réfère toujours à une région active de la pile.


EDIT Pour être absolument clair à nouveau (s'il n'était pas déjà clair de l'exemple ci-dessous) , le point ici n'est pas si ref / out peut seul point sur la pile. C'est que quand cela pointe sur la pile, il est garanti par les règles de la langue de ne pas devenir un pointeur pendant. Cette garantie est nécessaire (et pertinente / intéressante ici) car la pile ne résoue que les informations conformément aux exits d'appel de méthode, sans vérification pour garantir que les référateurs existent toujours.

inversement lorsque ref / out fait référence aux objets du tas de GC, il n'est pas surprenant que ces objets puissent être conservés en vie aussi longtemps que nécessaire: le tas de gc est conçu précisément dans le but de retenir des objets pour une longueur de temps requis par leurs référents et fournit un épinglant (voir exemple ci-dessous) pour prendre en charge les situations dans lesquelles l'objet ne doit pas être déplacé par le compactage GC.


Si vous jouez avec Interop en code dangereux, vous trouvera que ref est très étroitement lié aux pointeurs. Par exemple, si une interface COM est déclarée comme ceci: xxx

L'ensemble interopment le transformera en ceci: xxx

Et vous pouvez faire cela pour l'appeler (je crois que les trucs INTEROP COMM s'occupent d'épingler le tableau): xxx

en d'autres termes, ref au premier octet vous accède à tout cela; C'est apparemment un pointeur au premier octet.


2 commentaires

Vous pouvez ++ sur un argument REF Bien, mais cela ne signifie pas la même chose.


De plus, " ref et out se réfèrent toujours à une région active de la pile" est tout à fait faux. Votre propre exemple crée un ref dans un objet sur le tas de gc.



1
votes

La réponse courte est oui (fonctionnalité similaire, mais pas exactement le même mécanisme). En tant que note latérale, si vous utilisez FXCop pour analyser votre code, en utilisant out et ref entraînera une erreur "Microsoft.Design" de "CA1045: DonotpassTypesByReference." < / p>


0 commentaires

1
votes

La bonne chose à propos de l'utilisation out est que vous êtes assuré que l'article se verra attribuer une valeur - vous obtiendrez une erreur de compilation si non.


0 commentaires

2
votes

En réalité, je les comparerais à des références C ++ plutôt que des pointeurs. Les pointeurs, en C ++ et C, sont un concept plus général et les références feront ce que vous voulez.

Tous sont sans aucun doute des pointeurs sous les couvertures, bien sûr.


3 commentaires

Syntaxiquement, ils ressemblent à des pointeurs de plus près, car vous devez préparer ref , tout comme vous devez préparer & pour obtenir un pointeur en C / C ++.


(Je veux dire sur le site d'appel.)


Donc, ils sont vraiment quelque part au milieu (comme vous n'êtes pas obligé de le désirer lorsque vous en lisez / écrit).



3
votes

ref et out ne sont utilisés que avec des arguments de fonction pour signifier que l'argument doit être transmis par référence au lieu de la valeur. Dans ce sens, oui, ils sont un peu comme des pointeurs de C ++ (plus comme des références réellement). En savoir plus à ce sujet dans Cet article .


0 commentaires

1
votes

Alors que les comparaisons sont dans l'oeil du spectateur ... je dis non. 'Ref' change la Convention d'appel mais pas le type des paramètres. Dans votre exemple C ++, D1 et D2 sont de type INT *. En C #, ils sont toujours int32, ils arrivent simplement à être adoptés par référence au lieu de la valeur.

D'ailleurs, votre code C ++ ne échange pas vraiment ses entrées dans le sens traditionnel. Généraliser comme ça, comme: xxx

... ne fonctionnera pas à moins que tous les types t ont des constructeurs de copie, et même alors sera beaucoup plus inefficace que d'échanger des pointeurs.


1 commentaires

Je ne pense pas que votre analogie fonctionne tout à fait; Considérons int * contre const int * en C ++. Const est un qualificatif qui limite l'utilisation du type qu'il s'applique à, de la transformer efficacement à un type différent. Mais lorsque C ++ est compilé à IL, const est transformé en une sorte de modificateur personnalisé sur un type plutôt que de définir un type différent dans le système de type CLI. Cela montre que "type" dans la langue est séparé du "type" au cours de l'exécution. De la même manière, ref limite ce que vous pouvez faire avec l'objet (vous ne pouvez pas la capturer dans une Lambda, par exemple), ce qui fait partie du système de type C #, mais pas de CLI's.