W Javie throws
słowo kluczowe pozwala metodzie zadeklarować, że sama nie obsłuży wyjątku, ale raczej wyrzuci go do metody wywołującej.
Czy istnieje podobne słowo kluczowe / atrybut w C #?
Jeśli nie ma odpowiednika, w jaki sposób możesz osiągnąć ten sam (lub podobny) efekt?
c#
java
exception-handling
throws
Louis Rhys
źródło
źródło
Op pyta o C # odpowiednik
throws
klauzuli Java - nie othrow
słowo kluczowe. Jest to używane w sygnaturach metod w Javie, aby wskazać, że może zostać zgłoszony sprawdzony wyjątek.W języku C # nie ma bezpośredniego odpowiednika wyjątku sprawdzanego w Javie. C # nie ma równoważnej klauzuli podpisu metody.
// Java - need to have throws clause if IOException not handled public void readFile() throws java.io.IOException { ...not explicitly handling java.io.IOException... }
przetłumaczyć na
// C# - no equivalent of throws clause exceptions are unchecked public void ReadFile() { ...not explicitly handling System.IO.IOException... }
źródło
Tak, to stary wątek, jednak często znajduję stare wątki, gdy szukam odpowiedzi w Google, więc pomyślałem, że dodam coś przydatnego, co znalazłem.
Jeśli korzystasz z programu Visual Studio 2012, istnieje wbudowane narzędzie, którego można użyć, aby zezwolić na ekwiwalent „rzutów” na poziomie środowiska IDE.
Jeśli używasz komentarzy dokumentacji XML , jak wspomniano powyżej, możesz użyć tagu <exception>, aby określić typ wyjątku zgłaszanego przez metodę lub klasę, a także informacje o tym, kiedy lub dlaczego jest on generowany.
przykład:
/// <summary>This method throws an exception.</summary> /// <param name="myPath">A path to a directory that will be zipped.</param> /// <exception cref="IOException">This exception is thrown if the archive already exists</exception> public void FooThrowsAnException (string myPath) { // This will throw an IO exception ZipFile.CreateFromDirectory(myPath); }
źródło
throws
prawdopodobnie nic nie znaczy dla środowiska wykonawczego, poza informacją dla programisty. Podobnie @mvanella wskazał tutaj, że C # robi dokładnie to samo. Zakładam, że już wiesz, że ta „dokumentacja xml” ma ważniejszy cel. Wiem, że ten wątek jest stary.throws
klauzuli lub wyrzucone przezthrow
polecenie. Oznacza to, że jeśli wystąpi wyjątek RunTimeException i nie jest obsługiwany w tej samej metodzie, w której występuje, wykonanie zostanie zatrzymane w tym miejscu.Oto odpowiedź na podobne pytanie, które właśnie znalazłem na bytes.com :
źródło
Po przejrzeniu większości odpowiedzi tutaj, chciałbym dodać kilka myśli.
Poleganie na komentarzach do dokumentacji XML i oczekiwanie, że inni będą na nich polegać, to kiepski wybór. Większość kodu C #, z którym się spotkałem, nie dokumentuje metod całkowicie i spójnie z komentarzami dokumentacji XML. A potem jest większy problem, w jaki sposób bez sprawdzonych wyjątków w C # można udokumentować wszystkie wyjątki, które metoda generuje, aby użytkownik interfejsu API wiedział, jak obsługiwać je wszystkie indywidualnie? Pamiętaj, że wiesz tylko o tych, które rzucasz sobie za pomocą słowa kluczowego throw w swojej implementacji. Interfejsy API, których używasz w implementacji metody, mogą również generować wyjątki, o których nie wiesz, ponieważ mogą nie być udokumentowane i nie obsługujesz ich w swojej implementacji, więc wybuchną w obliczu wywołującego metoda. Innymi słowy,
Andreas połączył wywiad z Andersem Hejlsbergiem w odpowiedziach tutaj na temat tego, dlaczego zespół projektowy C # zdecydował się na sprawdzone wyjątki. Ostateczna odpowiedź na pierwotne pytanie jest ukryta w tym wywiadzie:
Innymi słowy, nikogo nie powinno interesować, jakiego rodzaju wyjątków można się spodziewać w przypadku konkretnego interfejsu API, ponieważ zawsze będziesz je łapać wszędzie. A jeśli naprawdę chcesz obchodzić się z określonymi wyjątkami, to jak sobie z nimi poradzić, zależy od ciebie, a nie od kogoś, kto definiuje sygnaturę metody za pomocą czegoś takiego jak słowo kluczowe Java throws, wymuszając określoną obsługę wyjątków u użytkownika API.
-
Osobiście jestem tu rozdarty. Zgadzam się z Andersem, że zaznaczenie wyjątków nie rozwiązuje problemu bez dodania nowych, innych problemów. Podobnie jak w przypadku komentarzy do dokumentacji XML, rzadko widzę kod C # zawierający wszystko, co jest opakowane w bloki try last. Wydaje mi się, że to rzeczywiście jedyna opcja i coś, co wydaje się dobrą praktyką.
źródło
Faktycznie brak sprawdzania wyjątków w C # można uznać za dobrą lub złą rzecz.
Osobiście uważam to za dobre rozwiązanie, ponieważ sprawdzone wyjątki powodują następujące problemy:
Z tego powodu w większości większych aplikacji często zobaczysz następujący wzorzec po zaznaczeniu Wyjątki:
try { // Some Code } catch(SomeException ex){ throw new RuntimeException(ex); }
Co zasadniczo oznacza emulowanie sposobu, w jaki C # / .NET obsługuje wszystkie wyjątki.
źródło
Pytasz o to:
Ponowne zgłoszenie wyjątku
public void Method() { try { int x = 0; int sum = 100/x; } catch(DivideByZeroException e) { throw; } }
lub
static void Main() { string s = null; if (s == null) { throw new ArgumentNullException(); } Console.Write("The string s is null"); // not executed }
źródło
throw
. Używając go, ślad stosu nie zostanie utracony.Istnieją pewne przelotne podobieństwa między .Net CodeContract
EnsuresOnThrow<>
athrows
deskryptorem java , ponieważ oba mogą sygnalizować wywołującemu jako typ wyjątku, który może zostać wywołany z funkcji lub metody, chociaż istnieją również duże różnice między 2:EnsuresOnThrow<>
wykracza poza zwykłe określenie, które wyjątki mogą zostać rzucone, ale także określa warunki, w których są one gwarantowane - może to być dość uciążliwy kod w wywołanej metodzie, jeśli warunek wyjątku nie jest łatwy do zidentyfikowania. Javathrows
zapewnia wskazanie, które wyjątki mogą zostać wyrzucone (tj. IMO fokus w .Net znajduje się wewnątrz metody, która kontraktuje, aby udowodnićthrow
, podczas gdy w Javie fokus przenosi się do wywołującego, aby potwierdzić możliwość wystąpienia wyjątku).throws
dla tego samego wyjątku w swoim interfejsie.Kod kontraktów instrukcja tutaj
źródło
Jeśli celem metody C # jest tylko zgłoszenie wyjątku (jak mówi typ powrotu js), polecam po prostu zwrócić ten wyjątek. Zobacz przykład poniżej:
public EntityNotFoundException GetEntityNotFoundException(Type entityType, object id) { return new EntityNotFoundException($"The object '{entityType.Name}' with given id '{id}' not found."); } public TEntity GetEntity<TEntity>(string id) { var entity = session.Get<TEntity>(id); if (entity == null) throw GetEntityNotFoundException(typeof(TEntity), id); return entity; }
źródło
Dla tych, którzy się zastanawiają, nie musisz nawet definiować tego, co złapiesz, aby przekazać to do następnej metody. Jeśli chcesz, aby cała obsługa błędów była w jednym głównym wątku, możesz po prostu złapać wszystko i przekazać dalej w ten sposób:
try { //your code here } catch { //this will throw any exceptions caught by this try/catch throw; }
źródło