Straż może poprawić przejrzystość
Kiedy używasz strażnika, masz znacznie większe oczekiwania, że strażnik odniesie sukces i jest dość ważne, że jeśli to się nie powiedzie, po prostu chcesz wcześniej wyjść z lunety . Tak jak Ty pilnujesz, aby sprawdzić, czy plik / obraz istnieje, czy tablica jest pusta, czy nie.
func icon() -> UIImage {
guard let image = UIImage(named: "Photo") else {
return UIImage(named: "Default")! //This is your fallback
}
return image //-----------------you're always expecting/hoping this to happen
}
Jeśli napiszesz powyższy kod za pomocą if-let, przekaże on programiście czytającemu, że jest to bardziej 50-50. Ale jeśli używasz guard, dodajesz klarowności do swojego kodu i oznacza to, że spodziewam się, że to zadziała w 95% przypadków ... jeśli kiedykolwiek się nie powiedzie, nie wiem, dlaczego miałoby to działać; jest to bardzo mało prawdopodobne ... ale zamiast tego po prostu użyj tego domyślnego obrazu lub po prostu potwierdź za pomocą sensownej wiadomości opisującej, co poszło nie tak!
Unikaj, guard
gdy powodują efekty uboczne, osłony powinny być używane jako naturalny przepływ. Unikaj strażników, gdy else
klauzule wprowadzają skutki uboczne. Strażnicy ustanawiają wymagane warunki do prawidłowego wykonania kodu, oferując wczesne wyjście
Kiedy wykonujesz znaczące obliczenia w dodatniej gałęzi, refaktoryzuj instrukcję z if
do guard
i zwraca wartość rezerwową w else
klauzuli
Od: Książka Swift Style Erica Sadun
Również w wyniku powyższych sugestii i czystego kodu jest bardziej prawdopodobne, że będziesz chciał / musiał dodać potwierdzenia do nieudanych instrukcji ochrony, po prostu poprawia czytelność i wyjaśnia innym programistom, czego się spodziewasz.
guard let image = UIImage(named: selectedImageName) else { // YESSSSSS
assertionFailure("Missing \(selectedImageName) asset")
return
}
guard let image = UIImage(named: selectedImageName) else { // NOOOOOOO
return
}
Od: Książka Swift Style Erica Sadun + kilka modyfikacji
(nie będziesz używać potwierdzeń / warunków wstępnych dla if-let
s. To po prostu nie wydaje się właściwe)
Korzystanie ze strażników pomaga również zwiększyć przejrzystość, omijając piramidę zagłady. Zobacz odpowiedź Nitina .
Guard tworzy nową zmienną
Jest jedna ważna różnica, której moim zdaniem nikt dobrze nie wyjaśnił.
Jednak oba guard let
i if let
rozpakuj zmienną
Wraz z guard let
tobą tworzysz nową zmienną, która będzie istniała poza else
instrukcją.
Ze if let
ty nie tworzysz każdy nowy zmiennej po else, wystarczy tylko wprowadzić blok kodu jeśli opcjonalny nie jest zerowe. Nowo utworzona zmienna istnieje tylko wewnątrz bloku kodu, a nie po!
guard let:
func someFunc(blog: String?) {
guard let blogName = blog else {
print("some ErrorMessage")
print(blogName) // will create an error Because blogName isn't defined yet
return
}
print(blogName) // You can access it here ie AFTER the guard statement!!
//And if I decided to do 'another' guard let with the same name ie 'blogName' then I would create an error!
guard let blogName = blog else { // errorLine: Definition Conflicts with previous value.
print(" Some errorMessage")
return
}
print(blogName)
}
if-let:
func someFunc(blog: String?) {
if let blogName1 = blog {
print(blogName1) // You can only access it inside the code block. Outside code block it doesn't exist!
}
if let blogName1 = blog { // No Error at this line! Because blogName only exists inside the code block ie {}
print(blogName1)
}
}
Aby uzyskać więcej informacji if let
, zobacz: Dlaczego ponowna deklaracja opcjonalnego powiązania nie powoduje błędu
Ochrona wymaga wyjścia z lunety
(Wspomniane również w odpowiedzi Roba Napiera):
MUSISZ guard
zdefiniować wewnątrz func. Jego głównym celem jest przerwanie / powrót / wyjście z zakresu, jeśli warunek nie jest spełniony:
var str : String?
guard let blogName1 = str else {
print("some error")
return // Error: Return invalid outside of a func
}
print (blogName1)
Na if let
nie trzeba go mieć w środku każdej func:
var str : String?
if let blogName1 = str {
print(blogName1) // You don't get any errors!
}
guard
vs if
Warto zauważyć, że jest to bardziej właściwe, aby zobaczyć jak to pytanie guard let
vs if let
i guard
kontra if
.
Samodzielny if
nie rozpakowuje się, podobnie jak samodzielny guard
. Zobacz przykład poniżej. Nie kończy się wcześniej, jeśli wartość to nil
. Brak wartości opcjonalnych. Po prostu wychodzi wcześnie, jeśli warunek nie jest spełniony.
let array = ["a", "b", "c"]
func subscript(at index: Int) -> String?{
guard index > 0, index < array.count else { return nil} // exit early with bad index
return array[index]
}
if let
gdynon-nil
sprawa jest ważna. Użyj,guard
gdynil
przypadek przedstawia jakiś rodzaj błędu.