Vraag Het verwerken van een geforceerde downcast als optioneel levert nooit 'nul' op


Ik heb met Swift gespeeld en ontdekt dat wanneer ik een object cast dat in een woordenboek moet worden ingevoegd, ik een rare waarschuwing krijg: Treating a forced downcast to 'String' as optional will never produce 'nil'. Als ik het vervang as met as? dan verdwijnt de waarschuwing.

func test() -> AnyObject! {
  return "Hi!"
}

var dict = Dictionary<String,String>()
dict["test"]=test() as String'

De documentatie van Apple zegt het volgende

Omdat downcasting kan falen, bestaat de operator van het type cast in twee verschillende vormen. Het optionele formulier, as?, retourneert een optionele waarde van het type waarnaar u probeert te downcasten. De gedwongen vorm, as, probeert de neergegooide en force-unwraps het resultaat als een enkele samengestelde actie.

Ik ben onduidelijk waarom as? in plaats van as is hier correct. Sommige testen laten zien dat als ik test () verander om een ​​Int in plaats van een String terug te sturen, de code zal stoppen met een fout als ik doorga as. Als ik overschakelen naar gebruik as? dan zal de code gewoon doorgaan met de uitvoering en die instructie overslaan (dict blijft leeg). Ik weet echter niet zeker waarom dit de voorkeur verdient. Naar mijn mening, zou ik liever hebben dat het programma werd afgesloten met een fout en liet me weten dat de cast niet succesvol was, negeer dan gewoon de foutieve verklaring en blijf uitvoeren.

Volgens de documentatie zou ik de gedwongen vorm moeten gebruiken "alleen als je zeker weet dat de downcast altijd zal lukken." In dit geval ben ik er zeker van dat de downcast altijd zal slagen, omdat ik het weet test() kan alleen een String retourneren, dus ik neem aan dat dit een perfecte situatie is voor de geforceerde vorm van down casting. Dus waarom geeft de compiler me een waarschuwing?


23
2018-06-14 19:38


oorsprong


antwoorden:


Laten we uw laatste regel van dichterbij bekijken en ontploffen om te zien wat er gebeurt:

let temporaryAnyObject = test()
let temporaryString = temporaryAnyObject as String
dict["test"] = temporaryString

De fout bevindt zich op de tweede regel, waar u de compiler vertelt om dit af te dwingen temporaryAnyObject is absoluut een String. De code compileert nog steeds (ervan uitgaande dat je waarschuwingen niet als fouten verwerkt), maar crasht als temporaryAnyObject is eigenlijk geen String.

De weg as werkt, zonder ?, is in feite zeggen "behandel vanaf nu het resultaat van deze uitdrukking als dat type ALS het resultaat eigenlijk van dat type is, anders zijn we inconsistent geworden en kunnen niet meer worden uitgevoerd.

De weg as? werkt (met de ?) zegt "behandel vanaf nu het resultaat van deze uitdrukking als dat type ALS het resultaat eigenlijk van dat type is, anders is het resultaat van deze uitdrukking nil.

Dus in mijn ontplofte voorbeeld hierboven, als test() komt wel terug String, dan de as downcast lukt, en temporaryString is nu een String. Als test() keert niet terug String, maar zeg een Int of iets anders dat niet is onderverdeeld in String, dan is het as mislukt en de code kan niet langer worden voortgezet.

Dit komt omdat je, als ontwikkelaar in volledige controle, het systeem hebt verteld om zich op deze manier te gedragen door het optionele niet te plaatsen ? indicator. De as commando betekent specifiek dat je geen optioneel gedrag duldt en je moet die downcast laten werken.

Als u de ?, dan temporaryString zou zijn nil, en de derde regel zou eenvoudig het "test" sleutel / waarde paar uit het woordenboek verwijderen.

Dit lijkt misschien vreemd, maar dat is alleen omdat dit het tegenovergestelde standaardgedrag is van vele talen, zoals Obj-C, die alles standaard als optioneel behandelen, en vertrouwen op u om uw eigen controles en beweringen te plaatsen.

Bewerken - Snel 2 bijwerken

Sinds Swift 2, de geforceerde, failable downcast-operator as is verwijderd en vervangen door as!, wat veel sneller is. Het gedrag is hetzelfde.


36
2018-06-14 20:38



 U kunt deze waarschuwing vanuit twee hoeken oplossen. 1. De waarde die u terugkrijgt 2. Het type dat u bent verwacht terugbrengen. Het andere antwoord spreekt over de eerste hoek. Ik spreek over de 2e hoek

Dit komt omdat je een a retourneert gedwongen uitgepakt en gegoten waarde voor een facultatief. De compiler is als, "Als je echt alle optionals gewoon wilt forceren, waarom maak je dan niet gewoon de verwachte return-parameter als een niet-optionele


2
2017-10-19 19:06