Domanda

Ho appena fatto uno Swap di routine in C# come questo:

static void Swap(ref int x, ref int y)
{
    int temp = x;
    x = y;
    y = temp;
}

Fa la stessa cosa che questo codice C++ fa:

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

Così sono le ref e out parole chiave come puntatori per C# senza l'utilizzo di unsafe codice?

È stato utile?

Soluzione

Sono più limitata. Si può dire ++ in un puntatore, ma non su un ref o out.


Modifica una certa confusione nei commenti, in modo da essere assolutamente chiaro: il punto qui è quello di confrontare con le funzionalità di puntatori. Non è possibile eseguire la stessa operazione come ptr++ su un ref / out, cioè renderlo indirizzo di una posizione adiacente nella memoria. E 'vero (ma irrilevante qui) che è possibile eseguire l'equivalente di (*ptr)++, ma che sarebbe quello di confrontarlo con le funzionalità di valori , non puntatori.


E 'una scommessa sicura che essi sono internamente solo i puntatori, perché lo stack non viene spostato e C # è organizzato con cura in modo che ref e out si riferiscono sempre a una regione attiva della pila.


Modifica Per essere assolutamente chiaro ancora una volta (se non era già chiaro dal esempio qui sotto), il punto qui non è che ref / out può solo punto a la pila. E 'che quando che punti a pila, è garantito dal regime linguistico non diventare un puntatore penzoloni. Questa garanzia è necessario (e pertinente / interessante qui) perché lo stack appena scarta informazioni in conformità con le uscite metodo di chiamata, senza controlli per garantire che esistono ancora eventuali referenti.

Viceversa quando ref / out riferisce agli oggetti nel mucchio GC non è una sorpresa che tali oggetti possano essere mantenuto in vita il tempo necessario: il mucchio GC è progettato proprio allo scopo di oggetti di ritegno per un certo periodo di tempo necessario dai loro referenti, e fornisce pinning (vedi esempio sotto) per supportare situazioni in cui l'oggetto non deve essere spostato da GC compattazione.


Se mai giocare con interoperabilità nel codice non sicuro, troverete che ref è strettamente correlata ai puntatori. Ad esempio, se un interfaccia COM viene dichiarata in questo modo:

HRESULT Write(BYTE *pBuffer, UINT size);

L'assembly di interoperabilità si trasformerà in questo modo:

void Write(ref byte pBuffer, uint size);

E si può fare questo a chiamarla (credo che la roba di interoperabilità COM si prende cura di pinning matrice):

byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);

In altre parole, ref al primo byte si ottiene l'accesso a tutto questo; è apparentemente un puntatore al primo byte.

Altri suggerimenti

parametri di riferimento in C # possono essere utilizzati per sostituire una uso di puntatori, sì. Ma non tutti.

Un altro uso comune per i puntatori è un mezzo per iterare su un array. Out / parametri ref non può farlo, quindi no, non lo sono "lo stesso come puntatori".

ref e out vengono utilizzati solo con argomenti di funzione per indicare che l'argomento deve essere passato per riferimento invece di valore. In questo senso, sì, sono un po 'come puntatori in C ++ (più come riferimenti in realtà). Per saperne di più su di esso nel questo articolo .

In realtà, mi piacerebbe confrontarle con riferimenti C ++ piuttosto che puntatori. I puntatori, in C ++ e C, sono un concetto più generale, ed i riferimenti farà quello che vuoi.

Tutti questi sono puntatori senza dubbio sotto le coperte, naturalmente.

La cosa bella con il è che avrete la garanzia che l'articolo sarà assegnato un valore -. Si otterrà un errore di compilazione, se non

Mentre i confronti sono nell'occhio di chi guarda...ti dico di no.'ref', cambia il convenzione di chiamata ma non l' tipo dei parametri.Nel tuo esempio C++, d1 e d2 sono di tipo int*.In C# sono ancora Int32, hanno appena capita di essere passati per riferimento invece del valore.

A proposito, il tuo codice C++ in realtà non scambiare i propri ingressi in senso tradizionale.Generalizzando piace così:

template<typename T>
void swap(T *d1, T *d2)
{
    T temp = *d1;
    *d1 = *d2;
    *d2 = temp;
}

...non funzionano a meno che tutti i tipi di T sono costruttori di copia, e anche allora sarà molto più inefficiente di scambio di puntatori.

La risposta breve è sì (funzionalità simile, ma non esattamente lo stesso meccanismo). Come nota a margine, se si utilizza FxCop per analizzare il codice, utilizzando out e ref si tradurrà in un errore "Microsoft.Design" di "CA1045:. DoNotPassTypesByReference"

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top