Mam klasę Animal
i jej podklasę Dog
. Często koduję następujące linie:
if (animal is Dog)
{
Dog dog = animal as Dog;
dog.Name;
...
}
Dla zmiennej Animal animal;
.
Czy jest jakaś składnia, która pozwala mi napisać coś takiego:
if (Dog dog = animal as Dog)
{
dog.Name;
...
}
c#
casting
if-statement
Michael
źródło
źródło
bool
warunek?null
=false
W C #; C # zezwala tylko na rzeczywiste boole lub rzeczy niejawnie konwertowane na bools wif
warunkach. Ani wartości null, ani żaden z typów całkowitych nie są niejawnie konwertowane na bools.Odpowiedzi:
Poniższa odpowiedź została napisana lata temu i aktualizowana z biegiem czasu. Począwszy od C # 7, możesz używać dopasowywania wzorców:
Zauważ, że
dog
poif
instrukcji nadal znajduje się w zakresie , ale nie jest ostatecznie przypisany.Nie, nie ma. Bardziej idiomatyczne jest jednak napisanie tego:
Biorąc pod uwagę, że „jak następuje, jeśli” jest prawie zawsze używane w ten sposób, bardziej sensowne może być wprowadzenie operatora, który wykonuje obie części za jednym razem. To nie jest obecnie w C # 6, ale może być częścią C # 7, jeśli propozycja dopasowania wzorca zaimplementowano .
Problem polega na tym, że nie możesz zadeklarować zmiennej w części warunkowej
if
instrukcji 1 . Najbliższe podejście, jakie przychodzi mi do głowy, to:To po prostu paskudne ... (Właśnie to wypróbowałem i działa. Ale proszę, nie rób tego. Och, i możesz zadeklarować
dog
użycievar
oczywiście .)Oczywiście możesz napisać metodę rozszerzającą:
Następnie zadzwoń za pomocą:
Alternatywnie możesz połączyć te dwa elementy:
Możesz także użyć metody rozszerzenia bez wyrażenia lambda w bardziej przejrzysty sposób niż pętla for:
Następnie:
1 Możesz przypisywać wartości w
if
instrukcjach, chociaż rzadko to robię. To nie to samo, co deklarowanie zmiennych. To nie jest strasznie nietypowe dla mnie zrobić wwhile
chociaż kiedy czyta strumienie danych. Na przykład:W dzisiejszych czasach zwykle wolę używać opakowania, które pozwala mi używać,
foreach (string line in ...)
ale postrzegam powyższe jako dość idiomatyczny wzór. To zwykle nie miło mieć skutki uboczne w obrębie stanu, ale alternatywy obejmują zazwyczaj powielania kodu, a gdy wiesz, ten wzór jest to łatwe, aby uzyskać prawo.źródło
EVIL EVIL EVIL
, ale nie jestem pewien .AsEither(...)
, myślę, że jest to trochę jaśniejsze niżAsIf(...)
, więc mogę pisaćmyAnimal.AsEither(dog => dog.Woof(), cat => cat.Meeow(), unicorn => unicorn.ShitRainbows())
.Jeśli się
as
nie powiedzie, zwracanull
.źródło
if
instrukcji, a nie w zakresie zewnętrznym.if
może mieć wynik bool i przypisanie.Dog dog; if ((dog = animal as Dog) != null) { // Use Dog }
ale to wciąż wprowadza zmienną w zakresie zewnętrznym.Państwo może przypisać wartość do zmiennej, jak długo już istnieje zmienna. Możesz również określić zakres zmiennej, aby umożliwić późniejsze użycie tej nazwy zmiennej w tej samej metodzie, jeśli jest to problem.
zarozumiały
pobiera dane wyjściowe:
Wzorzec przypisania zmiennych w teście jest również używany przy odczytywaniu bloków bajtów ze strumieni, na przykład:
Zastosowany powyżej wzorzec zakresu zmiennych nie jest jednak szczególnie powszechnym wzorcem kodu i gdybym zobaczył, że jest używany w całym miejscu, szukałbym sposobu na jego refaktoryzację.
źródło
Prawdopodobnie będzie w C # 6.0. Ta funkcja jest nazywana „wyrażeniami deklaracji”. Widzieć
https://roslyn.codeplex.com/discussions/565640
dla szczegółów.
Proponowana składnia to:
Bardziej ogólnie, proponowana funkcja polega na tym, że jako wyrażenie można użyć lokalnej deklaracji zmiennej . Ta
if
składnia jest po prostu przyjemną konsekwencją bardziej ogólnej funkcji.źródło
Try*
(npTryParse
.). Ta funkcja nie tylko sprawia, że takie wywołania są jednym wyrażeniem (tak powinno być, IMO), ale także pozwala na czystsze określanie zakresu takich zmiennych. Jestem entuzjastycznie nastawiony do tego, abyout
parametrTry
metody był ograniczony do jej warunkowej; utrudnia to wprowadzanie pewnych typów błędów.Jedną z metod rozszerzających, które często piszę i używam, jest *
Które mogą być użyte w tej sytuacji jako
I wtedy
name
imię psa (jeśli jest to pies), w przeciwnym razie jest puste.* Nie mam pojęcia, czy to działa. Nigdy nie było wąskim gardłem w profilowaniu.
źródło
Idę pod prąd, ale może przede wszystkim robisz to źle. Sprawdzanie typu obiektu jest prawie zawsze zapachem kodu. Czy w twoim przykładzie wszystkie zwierzęta nie mają imienia? Następnie po prostu zadzwoń do Animal.name, bez sprawdzania, czy to pies, czy nie.
Alternatywnie, odwróć metodę, aby wywołać metodę na Animal, która robi coś inaczej w zależności od konkretnego typu Animal. Zobacz też: Polimorfizm.
źródło
Krótsza instrukcja
źródło
Oto dodatkowy brudny kod (choć nie tak brudny jak Jona :-)) zależny od modyfikacji klasy bazowej. Myślę, że oddaje intencję, ale być może mija się z celem:
źródło
Jeśli musisz wykonać wiele takich as-if, jeden po drugim (a użycie polimorfizmu nie jest opcją), rozważ użycie konstrukcji SwitchOnType .
źródło
Problem (ze składnią) nie dotyczy przypisania, ponieważ operator przypisania w C # jest prawidłowym wyrażeniem. Raczej jest z pożądaną deklaracją ponieważ deklaracje są instrukcjami.
Jeśli muszę napisać taki kod, czasami (w zależności od szerszego kontekstu) napiszę taki kod:
Powyższa składnia (która jest zbliżona do żądanej) ma zalety, ponieważ:
dog
poza theif
spowoduje błąd kompilacji, ponieważ nie ma przypisanej wartości w innym miejscu. (Oznacza to, że nie przydzielaj godog
gdzie indziej.)if/else if/...
(jest tylko tyle,as
ile potrzeba do wybrania odpowiedniej gałęzi; to duża sprawa której piszę to w tej formie, kiedy muszę).is/as
. (Ale także zrobione zDog dog = ...
formą.)Aby naprawdę odizolować się
dog
od reszty świata, można użyć nowego bloku:Miłego kodowania.
źródło
możesz użyć czegoś takiego
// Zadeklaruj zmienną bool temp = false;
źródło
Kolejne ZŁE rozwiązanie z metodami rozszerzającymi :)
Osobiście wolę czysty sposób:
źródło
Instrukcja if na to nie pozwala, ale pętla for tak.
na przykład
Jeśli sposób, w jaki to działa, nie jest od razu oczywisty, oto wyjaśnienie tego procesu krok po kroku:
iterację.
źródło
źródło
IDK, jeśli komuś to pomoże, ale zawsze możesz spróbować użyć TryParse do przypisania zmiennej. Oto przykład:
Łączna zmienna zostanie ogłoszony przed if.
źródło
Właśnie wstawiłem instrukcję if, aby utworzyć wiersz kodu, który wygląda jak to, co cię interesuje. Pomaga to tylko skompresować kod i okazało się, że jest bardziej czytelny, zwłaszcza podczas zagnieżdżania przypisań:
źródło
Wiem, że jestem super spóźniony na imprezę, ale pomyślałem, że opublikuję własne obejście tego dylematu, ponieważ jeszcze go tu nie widziałem (ani nigdzie w tej sprawie).
Dzięki temu możesz:
WAŻNA UWAGA: Jeśli chcesz używać TryAs () używając interfejsu, MUSISZ mieć ten interfejs dziedziczący IAble.
Cieszyć się! 🙂
źródło