Sono più limitati. Puoi dire ++ su un puntatore, ma non su un ref
o out
.
EDIT 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 di ptr++
su un ref
/out
, vale a dire farlo indirizzare una posizione adiacente in memoria. È vero (ma irrilevante qui) che è possibile eseguire l'equivalente di (*ptr)++
, ma sarebbe quello di confrontarlo con le capacità dei valori , non i 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
riferiscono sempre a una regione attiva della pila.
EDIT essere assolutamente chiari nuovamente (se non era già chiaro dall'esempio sotto), il punto qui non è che ref
/out
può solo punto alla pila. È quello quando punta allo stack, è garantito dalle regole del linguaggio per non diventare un puntatore pendente. Questa garanzia è necessaria (e rilevante/interessante qui) perché lo stack scarta semplicemente le informazioni in conformità con le uscite di chiamata del metodo, senza controlli per garantire che esistano ancora dei referrer.
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 richiesto dai loro referrer e fornisce il pinning (vedi esempio sotto) per supportare situazioni in cui l'oggetto non deve essere spostato da GC compacting.
Se mai giocare con interoperabilità nel codice non sicuro, troverete che ref
è strettamente correlata ai puntatori.Ad esempio, se un interfaccia COM è dichiarato così:
HRESULT Write(BYTE *pBuffer, UINT size);
L'assembly di interoperabilità si trasformarlo in questo:
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.
Si può '++' su un argomento 'ref' bene, ma non significa la stessa cosa. –
Inoltre, "ref" e "out" fanno sempre riferimento a una regione attiva dello stack "è completamente sbagliato. Il tuo esempio crea un 'ref' in un oggetto sull'heap gc. –