Questa domanda è stata l'oggetto del mio blog il 23 giugno 2011 . Grazie per l'ottima domanda!
Il team di C # lo sta prendendo in considerazione per C # 7. Vedi https://github.com/dotnet/roslyn/issues/5233 maggiori dettagli, .
AGGIORNAMENTO: la funzionalità è arrivata a C # 7!
Hai ragione; .NET supporta metodi che restituiscono riferimenti gestiti alle variabili. .NET supporta anche variabili locali che contengono riferimenti gestiti ad altre variabili. (Si noti tuttavia che .NET non supporta campi o array che contengono riferimenti gestiti ad altre variabili perché ciò complica eccessivamente la storia della garbage collection. Inoltre, i tipi di "riferimento gestito a variabile" non sono convertibili in oggetto e pertanto non possono essere utilizzati come digita argomenti su tipi o metodi generici.)
Il commentatore "RPM1984" per qualche motivo ha chiesto una citazione per questo fatto. RPM1984 Vi incoraggio a leggere la specifica CLI Partizione I Sezione 8.2.1.1, "Puntatori gestiti e tipi correlati" per informazioni su questa funzionalità di .NET.
È del tutto possibile creare una versione di C # che supporti entrambe queste funzionalità. Potresti quindi fare cose del genere
static ref int Max(ref int x, ref int y)
{
if (x > y)
return ref x;
else
return ref y;
}
e poi chiamalo con
int a = 123;
int b = 456;
ref int c = ref Max(ref a, ref b);
c += 100;
Console.WriteLine(b); // 556!
So empiricamente che è possibile creare una versione di C # che supporti queste funzionalità perché l'ho fatto . I programmatori avanzati, in particolare le persone che eseguono il porting di codice C ++ non gestito, spesso ci chiedono una maggiore capacità simile al C ++ di fare le cose con riferimenti senza dover uscire dal grosso martello di usare effettivamente i puntatori e bloccare la memoria ovunque. Utilizzando i riferimenti gestiti si ottengono questi vantaggi senza pagare il costo di rovinare le prestazioni della raccolta dei rifiuti.
Abbiamo preso in considerazione questa funzione e ne abbiamo effettivamente implementato abbastanza da mostrarlo ad altri team interni per ottenere il loro feedback. Tuttavia, in questo momento, sulla base delle nostre ricerche , riteniamo che la funzione non abbia un appeal sufficientemente ampio o casi di utilizzo convincenti da trasformarla in una vera funzionalità linguistica supportata . Abbiamo altre priorità più alte e una quantità limitata di tempo e sforzi disponibili, quindi non faremo presto questa funzione.
Inoltre, farlo correttamente richiederebbe alcune modifiche al CLR. Al momento il CLR considera i metodi di restituzione come legali ma non verificabili perché non abbiamo un rilevatore che rilevi questa situazione:
ref int M1(ref int x)
{
return ref x;
}
ref int M2()
{
int y = 123;
return ref M1(ref y); // Trouble!
}
int M3()
{
ref int z = ref M2();
return z;
}
M3 restituisce il contenuto della variabile locale M2, ma la durata di tale variabile è terminata! È possibile scrivere un rivelatore che determina gli usi dei ref-return che chiaramente non violano la sicurezza dello stack. Quello che faremmo è scrivere un tale rivelatore, e se il rivelatore non fosse in grado di provare la sicurezza dello stack, allora non permetteremmo l'uso dei ritorni di riferimento in quella parte del programma. Non è un'enorme quantità di lavoro di sviluppo per farlo, ma è un grande onere per i team di test per assicurarsi che abbiamo davvero tutti i casi. È solo un'altra cosa che aumenta il costo della funzionalità al punto in cui in questo momento i vantaggi non superano i costi.
Se riesci a descrivere per me perché vuoi questa funzione, lo apprezzerei molto . Più informazioni abbiamo da parte dei clienti reali sul motivo per cui lo desiderano, più è probabile che un giorno entrino nel prodotto. È una funzionalità carina e mi piacerebbe essere in grado di portarlo ai clienti in qualche modo se c'è abbastanza interesse.
(Vedi anche le domande correlate È possibile restituire un riferimento a una variabile in C #? E posso usare un riferimento all'interno di una funzione C # come C ++? )