Qualche prospettiva di quadro generale da aggiungere alle altre risposte utili ma più incentrate sui dettagli:
In Swift, il punto esclamativo appare in diversi contesti:
- Disimballaggio forzato:
let name = nameLabel!.text
- Opzionali impliciti da scartare:
var logo: UIImageView!
- Colata forzata:
logo.image = thing as! UIImage
- Eccezioni non gestite:
try! NSJSONSerialization.JSONObjectWithData(data, [])
Ognuno di questi è un costrutto di linguaggio diverso con un significato diverso, ma tutti hanno tre cose importanti in comune:
1. I punti esclamativi aggirano i controlli di sicurezza in fase di compilazione di Swift.
Quando usi !
Swift, stai essenzialmente dicendo: "Ehi, compilatore, so che pensi che qui possa accadere un errore , ma so con assoluta certezza che non lo farà mai".
Non tutto il codice valido si inserisce nella casella del sistema di compilazione del tempo di compilazione di Swift - o del controllo statico del tipo di qualsiasi lingua, del resto . Ci sono situazioni in cui puoi logicamente dimostrare che non si verificherà mai un errore, ma non puoi provarlo al compilatore . Ecco perché i designer di Swift hanno aggiunto queste funzionalità in primo luogo.
Tuttavia, ogni volta che lo usi !
, stai escludendo un percorso di recupero per un errore, il che significa che ...
2. I punti esclamativi sono potenziali arresti anomali.
Un punto esclamativo dice anche: "Ehi Swift, sono così certo che questo errore non può mai accadere che è meglio per te bloccare la mia intera app di quanto non lo sia per me codificare un percorso di recupero."
È un'affermazione pericolosa. esso può essere quella giusta: nel codice mission-critical in cui avete pensato duro a invarianti del codice, può essere che la produzione fasulla è peggio di un incidente.
Tuttavia, quando vedo !
in natura, raramente viene utilizzato in modo così consapevole. Invece, troppo spesso significa "questo valore era facoltativo e non pensavo davvero troppo al perché potesse essere nullo o a come gestire correttamente quella situazione, ma aggiungendo!
fatta compilare ... quindi il mio codice è corretto, giusto?"
Fai attenzione all'arroganza del punto esclamativo. Anziché…
3. I punti esclamativi sono usati con parsimonia.
Ognuno di questi !
costrutti ha una ?
controparte che ti costringe a gestire il caso di errore / zero:
- Involucro condizionale:
if let name = nameLabel?.text { ... }
- Optional:
var logo: UIImageView?
- Cast condizionali:
logo.image = thing as? UIImage
- Eccezioni zero-on-failure:
try? NSJSONSerialization.JSONObjectWithData(data, [])
Se sei tentato di usare !
, è sempre bene considerare attentamente perché non stai usando ?
. L'arresto anomalo del programma è davvero l'opzione migliore se l' !
operazione non riesce? Perché quel valore è opzionale / disponibile?
Esiste un ragionevole percorso di recupero che il tuo codice potrebbe prendere nel caso zero / errore? In tal caso, codificalo.
Se non può essere nulla, se l'errore non può mai accadere, allora c'è un modo ragionevole per rielaborare la tua logica in modo che il compilatore lo sappia? Se è così, fallo; il tuo codice sarà meno soggetto a errori.
Ci sono momenti in cui non esiste un modo ragionevole per gestire un errore e semplicemente ignorare l'errore - e quindi procedere con dati errati - sarebbe peggio dell'arresto anomalo. Quelli sono i tempi per usare lo scartamento forzato.
Cerco periodicamente tutto il mio codebase !
e controllo ogni suo utilizzo. Pochissimi usi resistono al controllo. (Al momento della stesura di questo documento, l'intero framework Siesta ne contiene esattamente due esempi .)
Questo non vuol dire che non dovresti mai usare il !
tuo codice - solo che dovresti usarlo consapevolmente e non renderlo mai l'opzione predefinita.