more concise way to downcast from optional?

I've seen this question come up a few times, but haven't seen any nice short solutions. The problem is that I've got a function which returns an optional value of a base type, and I want to safe cast it to a derived type. But the optional itself might be nil, or the cast might fail; I don't care about knowing why it failed if it does.


In C++, dynamic_cast<> handles both of these: if you dynamic cast a NULL it fails, if you get the type wrong it fails. But in swift, I can't see anyway of doing it other than doing a double let, which is annoyingly unwieldy. (Or repeating the function call itself which is a non-starter for performance reasons.)


let dd = [String:AnyObject]()

if let v1 = dd["foobar"],

let v2 = v1! as? WantedType {

// v2 is of type WantedType

}


Too much. Surely we can get this down to one line? I'm sure I've reinvented a wheel, but here goes anyway:


struct GuardedAs<U> {

var result:U?

init<T>(_ v: T?) { result = (v == nil ) ? nil : (v! as? U) }

}


Now I can guard and cast at the same time:


if let v2 = GuardedAs<WantedType>(dd["foobar"]).result {

// do stuff with v2

}



Anybody got anything better? Is there a way I can make this an extension directly in the Optional class itself? I'm really hating the lack of syntax for calling a generic function simply like myFunction<U>() when myFunction takes no arguments. So I have to fake it with a structure.


In most other respects, this is a lovely language to work with. C++ metaprogramming tied me in knots. Constraints on types for generics rock.

Answered by OOPer in 103264022

You might have some better examples, but the double-let example needs to be fixed as:

if let v1 = dd["foobar"],
    let v2 = v1 as? WantedType {
        // v2 is of type WantedType
}

(You have no need to put `!` after `v1` in the second `let`.)


And the more important thing is this example can be rewritten into single if-let:

if let v2 = dd["foobar"] as? WantedType {
    // v2 is of type WantedType
}

Not much worse than dynamic_cast, I think.

Accepted Answer

You might have some better examples, but the double-let example needs to be fixed as:

if let v1 = dd["foobar"],
    let v2 = v1 as? WantedType {
        // v2 is of type WantedType
}

(You have no need to put `!` after `v1` in the second `let`.)


And the more important thing is this example can be rewritten into single if-let:

if let v2 = dd["foobar"] as? WantedType {
    // v2 is of type WantedType
}

Not much worse than dynamic_cast, I think.

)>>I'm really hating the lack of syntax for calling a generic function simply like myFunction<U>() when myFunction takes no arguments. So I have to fake it with a structure.<<


We've had this discussion before.

If the function has no U type arguments you must be using type properties or methods inside myFunction, which probably means U satisfies some protocol.

In that case you may be able to add myFunction to the protocol.

If not you can fake it with a type parameter: myFunction<U>(uType:U.Type)

and call this like myFunction(uType:someU.self)


Jan E.

I feel dumb. I tried so many different casting combinations and I kept getting an error. I could have sworn I did the obvious as? WantedType in my (real) example (which was casting a UIViewConroller? from an extension inside UIViewController), but sigh, exactly what you said works this morning. Never mind, nothing to see here people.


Thank yoy.

more concise way to downcast from optional?
 
 
Q