EDYCJA: Zgadzam się z innymi, którzy twierdzą, że od wersji C # 6.0 filtry wyjątków są teraz całkiem dobrym sposobem:catch (Exception ex) when (ex is ... || ex is ... )
Tyle że nadal nienawidzę układu z jedną linią i osobiście ułożyłem kod w następujący sposób. Myślę, że jest to tak funkcjonalne, jak estetyczne, ponieważ uważam, że poprawia zrozumienie. Niektórzy mogą się nie zgadzać:
catch (Exception ex) when (
ex is ...
|| ex is ...
|| ex is ...
)
ORYGINALNY:
Wiem, że jestem trochę spóźniony na przyjęcie tutaj, ale święty dym ...
Przechodząc prosto do sedna, ten rodzaj powiela wcześniejszą odpowiedź, ale jeśli naprawdę chcesz wykonać wspólną akcję dla kilku typów wyjątków i utrzymać całość w porządku w ramach jednej metody, dlaczego po prostu nie użyć lambda / closure / inline funkcja zrobić coś takiego: Mam na myśli całkiem spore szanse, że zdasz sobie sprawę, że po prostu chcesz, aby to zamknięcie było odrębną metodą, z której możesz korzystać wszędzie. Ale wtedy będzie to bardzo łatwe, bez faktycznej zmiany reszty kodu strukturalnie. Dobrze?
private void TestMethod ()
{
Action<Exception> errorHandler = ( ex ) => {
// write to a log, whatever...
};
try
{
// try some stuff
}
catch ( FormatException ex ) { errorHandler ( ex ); }
catch ( OverflowException ex ) { errorHandler ( ex ); }
catch ( ArgumentNullException ex ) { errorHandler ( ex ); }
}
Nie mogę przestać się zastanawiać ( ostrzeżenie: trochę ironii / sarkazmu przed nami), dlaczego, do licha, podejmujesz te wszystkie wysiłki, aby po prostu zastąpić następujące:
try
{
// try some stuff
}
catch( FormatException ex ){}
catch( OverflowException ex ){}
catch( ArgumentNullException ex ){}
... z pewną szaloną odmianą tego następnego zapachu kodu, mam na myśli tylko po to, by udawać, że oszczędzasz kilka naciśnięć klawiszy.
// sorta sucks, let's be honest...
try
{
// try some stuff
}
catch( Exception ex )
{
if (ex is FormatException ||
ex is OverflowException ||
ex is ArgumentNullException)
{
// write to a log, whatever...
return;
}
throw;
}
Ponieważ z pewnością nie jest automatycznie bardziej czytelny.
To prawda, zostawiłem trzy identyczne przypadki z /* write to a log, whatever... */ return;
pierwszego przykładu.
Ale o to mi chodzi. Wszyscy słyszeliście o funkcjach / metodach, prawda? Poważnie. Napisz wspólną ErrorHandler
funkcję i wywołaj ją z każdego bloku catch.
Jeśli zapytasz mnie, drugi przykład (ze słowami kluczowymi if
i is
) jest zarówno znacznie mniej czytelny, a jednocześnie znacznie bardziej podatny na błędy podczas fazy konserwacji twojego projektu.
Faza konserwacji, dla każdego, kto może być stosunkowo nowy w programowaniu, będzie stanowić 98,7% lub więcej całkowitego czasu życia twojego projektu, a biedny schmuck wykonujący konserwację prawie na pewno będzie kimś innym niż ty. I jest bardzo duża szansa, że spędzą 50% swojego czasu na pracy przeklinając twoje imię.
I oczywiście FxCop szczeka na ciebie, więc musisz również dodać atrybut do swojego kodu, który ma dokładnie zip związany z działającym programem, i jest tylko po to, aby powiedzieć FxCop, aby zignorował problem, który w 99,9% przypadków jest całkowicie poprawne w oznaczaniu. I przepraszam, mogę się mylić, ale czy ten atrybut „ignoruj” nie jest tak naprawdę wkompilowany w twoją aplikację?
Czy umieszczenie całego if
testu w jednym wierszu uczyniłoby go bardziej czytelnym? Nie wydaje mi się To znaczy, już dawno temu inny programista gwałtownie argumentował, że umieszczenie większej ilości kodu w jednym wierszu sprawiłoby, że „działałby on szybciej”. Ale oczywiście był niesamowitym wariatem. Próba wyjaśnienia mu (z prostą twarzą - co było wyzwaniem), w jaki sposób interpreter lub kompilator podzieliłby tę długą linię na dyskretne instrukcje składające się z jednej instrukcji na linię - zasadniczo identyczny z wynikiem, gdyby poszedł naprzód i po prostu sprawił, że kod był czytelny, zamiast próbować sprytnie skompilować kompilator - nie miał na niego żadnego wpływu. Ale dygresję.
O ile mniej jest to czytelne, gdy dodasz trzy kolejne typy wyjątków, za miesiąc lub dwa od teraz? (Odpowiedź: robi się o wiele mniej czytelny).
Jednym z głównych punktów jest to, że większość formatowania tekstowego kodu źródłowego, na który wszyscy patrzymy każdego dnia, polega na tym, aby uświadomić innym ludziom, co tak naprawdę dzieje się podczas działania kodu. Ponieważ kompilator zamienia kod źródłowy w coś zupełnie innego i nie obchodzi go styl formatowania kodu. Więc też wszystko w jednej linii jest do kitu.
Tylko mówię...
// super sucks...
catch( Exception ex )
{
if ( ex is FormatException || ex is OverflowException || ex is ArgumentNullException )
{
// write to a log, whatever...
return;
}
throw;
}