Nowa wersja języka wprowadzi również ulepszenia w obsłudze wyjątków. Często tworzymy jeden wyjątek typu OperationFailedException, a w nim enum, który określa dlaczego operacja nie powiodła się tzn.:
public class OperationFailedException : Exception { public OperationFailedException(int statusCode) { StatusCode = statusCode; } public int StatusCode { get; set; } }
Co jeśli chcemy napisać obsługę wyjątków, ale wyłącznie tych ze statusem 5? Dzisiaj możemy łapać wszystkie wyjątki i sprawdzać jaki status został zwrócony:
try { throw new OperationFailedException(5); } catch(OperationFailedException e) { if (e.StatusCode != 5) throw; // recovery Console.WriteLine("Recovery"); }
Czasami jest więcej warunków i sprawa po prostu komplikuje się. W C# 6.0 możliwe jest łapanie wyjątków za pomocą filtra tzn.:
try { throw new OperationFailedException(5); } catch(OperationFailedException e) if(e.StatusCode==5) { // recovery Console.WriteLine("Recovery"); }
Wyłącznie OperationFailedException z StatusCode równym 5 będą wyłapywane. Oczywiście jak to ze wszystkimi ułatwieniami bywa, nie znaczy to, że powinniśmy tworzyć jeden wyjątek z wieloma statusami. Wciąż lepiej rozdzielać wyjątki na wiele klas. Czasami po prostu nie ma sensu tworzyć dwóch bardzo podobnych klas i lepiej zaimplementować to za pomocą jednej ale właśnie ze statusem.
Zajrzyjmy teraz do ILSpy:
private static void Main(string[] args) { try { throw new OperationFailedException(5); } object arg_09_0; OperationFailedException expr_0E = arg_09_0 as OperationFailedException; int arg_22_0; if (expr_0E == null) { arg_22_0 = 0; } else { OperationFailedException e = expr_0E; arg_22_0 = (((e.StatusCode == 5) > false) ? 1 : 0); } endfilter(arg_22_0); }
Tutaj widzimy pewną zmianę. Możemy zauważyć instrukcję endfilter. Tak naprawdę istniała ona od dawna w IL tylko C# nigdy jej nie wykorzystywał. Więcej informacji o instrukcji tutaj. W skrócie – to ona właśnie filtruje wyjątki na podstawie przekazanej flagi.