2009-02-09 16 views
14

I riferimenti in C# sono abbastanza simili a quelli in C++, tranne per il fatto che sono dati inutili.Perché C# non offre costanza simile a C++?

Perché è poi così difficile per il compilatore C# per supportare i seguenti:

  1. Membri funzioni contrassegnate const.
  2. Riferimenti a tipi di dati (diversi dalla stringa) contrassegnati con const, tramite i quali è possibile chiamare solo le funzioni membro const?

Credo che sarebbe davvero utile se C# supportasse questo. Per uno, aiuterà davvero l'abbandono gay apparentemente diffuso con il quale i programmatori C# restituiscono riferimenti nudi a dati privati ​​(almeno questo è quello che ho visto sul mio posto di lavoro).

Oppure c'è già qualcosa di equivalente in C# che mi manca? (Conosco le parole chiave readonly e const, ma in realtà non hanno lo scopo sopraindicato)

risposta

17

Ho il sospetto che ci sono alcune ragioni pratiche, e alcuni motivi teorici:

  • caso in cui la costanza applicano alla oggetto o di riferimento? Se è nel riferimento, dovrebbe essere solo in fase di compilazione o un po 'all'interno del riferimento stesso? Può qualcos'altro che ha un riferimento non costante allo stesso oggetto armeggiare con esso sotto il cofano?
  • Vorresti poterlo lanciare come puoi in C++? Non suona molto come qualcosa che vorresti su una piattaforma gestita ... ma che dire di tutte quelle volte in cui ha senso in C++?
  • La sintassi diventa complicata (IMO) quando più di un tipo è coinvolto in una dichiarazione: pensate a matrici, generici, ecc. Può diventare difficile calcolare esattamente quale bit è const.
  • Se non riesci a lanciarlo via, tutti devono farlo bene. In altre parole, sia i tipi di framework .NET che le altre librerie di terze parti che utilizzi devono fare la cosa giusta, oppure ti rimangono brutte situazioni in cui il tuo codice non può fare la cosa giusta a causa di un sottile problema con constness.

C'è un grande in termini di motivo per cui non può essere supportato ora però:

  • Compatibilità: non c'è alcun modo tutte le librerie sarebbero migrati correttamente ad esso, il che rende più o meno inutile :(

sono d'accordo che sarebbe utile avere una sorta di indicatore di costanza, ma non riesco a vedere che succede, ho paura.

EDIT: C'è stata una discussione su questa rabbia nella comunità Java da secoli. C'è un bel po 'di commenti sullo relevant bug che potresti trovare interessante.

+0

Grazie Jon. È illuminante. –

0

La domanda è: abbiamo bisogno di costanza in C#?

  1. Sono abbastanza sicuro che il jitter sa che il metodo indicato, non sta andando ad incidere l'oggetto stesso ed esegue corrispondenti ottimizzazioni automagicamente. (Forse attraverso l'emissione di call invece di callvirt?)

  2. non sono sicuro abbiamo bisogno di quelle, poiché la maggior parte dei pro di costanza sono le prestazioni correlate, si finisce al punto 1.

Oltre a ciò, C# ha la parola chiave readonly.

+1

Non sono d'accordo con la vostra affermazione che "la maggior parte dei pro della costanza sono correlati alle prestazioni" - Direi che la maggior parte sono legati alla correttezza e alla manutenibilità. –

+2

Non è per comodità di JITter, ma per il programmatore. In C++, se sto provando a modificare un oggetto const, il compilatore mi dà un errore. Quindi, ad esempio, posso restituire i riferimenti const dai miei metodi. In C# tutti sembrano essere riferimenti di ritorno che chiunque al di fuori può cambiare. Pericoloso! –

+0

@Frederick: Esattamente :) –

6

Come Jon ha già coperto (ovviamente) la correttezza costante non è così semplice come potrebbe sembrare. C++ lo fa in un modo. D lo fa in un altro modo (probabilmente più corretto/utile). C# flirta con esso ma non fa nulla di più audace, come hai scoperto (e probabilmente non andrà mai bene, come Jon ricoprì di nuovo).

Detto questo, credo che molte delle "ragioni teoriche" di Jon siano risolte nel modello di D.

In D (2.0), const funziona in modo molto simile al C++, tranne per il fatto che è completamente transitivo (quindi const applicato a un puntatore si applicherà all'oggetto puntato a, tutti i membri di quell'oggetto, qualsiasi puntatore dell'oggetto, oggetti hanno indicato ecc.) - ma è esplicito che questo solo si applica dalla variabile che hai dichiarato const (quindi se hai già un oggetto non-const e prendi un puntatore const su di esso, la variabile non const può ancora muta lo stato).

D introduce un'altra parola chiave - invariante - che si applica all'oggetto stesso. Ciò significa che nulla può mai cambiare lo stato una volta inizializzato.

La bellezza di questa disposizione è che un metodo const può accettare sia oggetti const sia oggetti invarianti. Poiché gli oggetti invarianti sono il pane e il burro del mondo funzionale, e il metodo const può essere contrassegnato come "puro" in senso funzionale, anche se può essere utilizzato con oggetti mutabili.

Rimettersi in carreggiata - Penso che sia il caso che siamo solo ora (la seconda metà degli ingenui) a capire come utilizzare al meglio const (e invariante). .Net è stato originariamente definito quando le cose erano più confuse, quindi non si è impegnato troppo - e ora è troppo tardi per il retrofit.

Mi piacerebbe vedere un porto di corsa D su .NET VM, anche se :-)

2

Non sarei sorpreso se fossero aggiunti tipi immutabili a una versione futura di C#. Ci sono già stati mosse in quella direzione con C# 3.0.

I tipi anonimi, ad esempio, sono immutabili.

Penso che, a seguito di estensioni progettate per abbracciare il parallelismo, sarà più probabile vedere l'immutabilità apparire sempre più.

Problemi correlati