Kako podesiti pametne telefone i računare. Informativni portal
  • Dom
  • Windows 10
  • Winforms ispravno rukovanje izuzetkom u c. Otklanjanje grešaka i rukovanje izuzetcima

Winforms ispravno rukovanje izuzetkom u c. Otklanjanje grešaka i rukovanje izuzetcima

konstante uslovne kompilacije. Omogućava vam da definirate konstante koje se kasnije koriste u metodi uvjetnog ispisa WriteIf klasa Debug i Trace. Snaga ovog mehanizma je u tome što se konstante mogu mijenjati u konfiguracijskoj datoteci projekta bez promjene projektnog koda ili potrebe da se ponovo kompajlira.

Visual Studio .Net Debugging i Workbench

Instrumentalno okruženje studija pruža programeru najviše širok raspon mogućnosti praćenja toka proračuna i praćenja stanja u kojima se proces proračuna nalazi. Jer svi su moderni instrumentalna okruženja organizovani na sličan način i dobro poznati programerima koji rade, dozvoliću sebi da se ne zadržavam na opisu mogućnosti okruženja.

Obrada izuzetaka

Kako god pouzdan kod bez obzira na to koliko je temeljno napisano, bez obzira na to koliko je detaljno otklanjanje grešaka, verzija koja je prebačena u rad i održavanje će naići na kršenje specifikacija tokom pokretanja. Razlog tome su gore navedeni zakoni softverski inženjeri. Ostaje u sistemu poslednja greška, postoje korisnici koji ne znaju specifikacije, a ako specifikacija može biti prekršena, onda će se ovaj događaj jednom dogoditi. Takve izuzetne situacije nastavak izvršavanja programa ili ono postane nemoguće (pokušaj neovlaštenog dijeljenja nultom operacijom, pokušaj upisivanja u zaštićeno memorijsko područje, pokušaj otvaranja nepostojeći fajl, pokušaj da se dobije nepostojeći zapis baze podataka), ili u nastaloj situaciji, upotreba algoritma će dovesti do pogrešnih rezultata.

Šta učiniti ako se to dogodi izuzetna situacija? Naravno da uvek postoji standardni način- prijaviti grešku i prekinuti izvršavanje programa. Jasno je da je ovo prihvatljivo samo za bezopasne aplikacije; čak i za kompjuterske igrice Ova metoda nije prikladna, a kamoli za kritične aplikacije!

U programskim jezicima za obradu izuzetne situacije ponudio najviše različiti pristupi.

Rukovanje izuzecima u C/C++ jezicima

Programski stil C karakteriše opisivanje metoda klase kao Booleove funkcije, vraća true ako se metoda normalno završava i false ako se dogodi izuzetna situacija. Poziv metode je ugrađen u if naredbu koja obrađuje grešku ako metoda ne uspije da se dovrši:

bool MyMethod(...)(...) if !MyMethod())(// rukovanje greškama) (//normalno izvršavanje)

Nedostaci ove šeme su jasni. Prvo, postoji malo informacija o uzroku greške, tako da ili kroz polja klase ili kroz argumente metode morate proći Dodatne informacije. Drugo, blok za obradu je ugrađen u svaki poziv, što dovodi do naduvavanja koda.

Stoga C/C++ koristi blok shemu try/catch, čija je suština sljedeća. Odjeljak programa u kojem se može pojaviti izuzetna situacija, je formatiran kao zaštićeni blok pokušaja. Ako prilikom njegovog izvršavanja postoji izuzetna situacija, tada je izvođenje bloka try s klasifikacijom izuzetaka prekinuto. Ovaj izuzetak počinje da se obrađuje od strane jednog od blokova catch koji odgovara tipu izuzetka. C/C++ koristi dvije takve sheme. Jedan od njih - šema obnove- odgovara takozvanim strukturnim, ili C-izuzecima. Druga šema - nema obnove- odgovara C++ izuzecima. U prvoj shemi, rukovatelj izuzetkom - blok catch - vraća kontrolu u neku tačku u bloku try. U drugoj šemi, kontrola se ne vraća u blok pokušaja.

Uz neke sintaksičke razlike šema obnove koristi se u VB/VBA jezicima.

Šema rukovanja izuzecima u C#

Jezik C# je naslijedio shemu izuzetaka jezika C++, praveći vlastita prilagođavanja. Pogledajmo bliže krug i počnimo sa sintaksom konstrukcije pokušaj-uhvati-konačno:

pokušaj (...) uhvatiti (T1 e1) (...) ... uhvatiti(Tk ek) (...) konačno (...)

Bilo gdje u tekstu modula gdje je blok sintaktički dozvoljen, blok se može učiniti zaštićenim dodavanjem ključne riječi try. Blok try može biti praćen blokovima catch pod nazivom blokovi za obradu izuzetaka, može ih biti nekoliko, a mogu i izostati. Završava ovaj niz konačno blokirati- blok finalizacije, koji takođe može nedostajati. Cijela ova struktura može biti ugniježđena - blok try može uključiti strukturu pokušaj-uhvati-konačno.

Dodavanje izuzetaka. Kreiranje objekata izuzetaka

U tijelu pokušajnog bloka može doći do toga izuzetna situacija, što dovodi do bacanje izuzetaka. Formalno bacanje izuzetka javlja se kada se izvrši naredba throw. Ovaj operator se najčešće izvršava u dubinama operativnog sistema, kada sistem komandi ili API funkcija ne može da radi svoj posao. Ali ovaj operater može biti dio tekst programa pokušati blokirati i izvršiti kada, kao rezultat analize, postane jasno da dalje normalan rad nemoguće.

Sintaktički, operator throw izgleda ovako:

baciti [izraz]

Izraz throw specificira objekat klase koji je potomak klase Exception. Obično je ovo novi izraz, koji stvara novi objekat. Ako nedostaje, trenutni izuzetak se vraća. Ako se izbaci izuzetak operativni sistem, onda sam klasifikuje izuzetak, kreira objekat odgovarajuće klase i automatski popunjava njegova polja.

U modelu koji razmatramo, izuzeci su objekti čija je klasa potomak klase Exception. Ova klasa i njeni brojni potomci su dio FCL biblioteke, iako su raštrkani po različitim imenskim prostorima. Svaka klasa specificira određeni tip izuzeci prema klasifikaciji usvojenoj u .Net Framework. Evo samo nekoliko klase izuzetaka iz System imenskog prostora: ArgumentException, ArgumentOutOfRangeException, ArithmeticException, BadImageFormatException, DivideByZeroException, OverflowException. Imenski prostor System.IO sadrži klase izuzetaka vezano za I/O probleme: DirectoryNotFoundException, FileNotFoundException i mnogi drugi. Svačija imena klase izuzetaka završiti riječju izuzetak. Dozvoljeno vam je da kreirate svoje klase izuzetaka, nasljeđujući ih od klase Exception.

Kada se izvede naredba throw, kreira se objekat te, čija TE klasa karakteriše trenutni izuzetak, a polja sadrže informacije o izuzetku koji se dogodio. izuzetna situacija. Izvršavanje naredbe throw uzrokuje zaustavljanje normalnog procesa izračunavanja. Ako se to dogodi u zaštićenom bloku pokušaja, tada počinje korak "hvatanje" izuzetka jedan od obrađivača izuzetaka.

Hvatanje izuzetka

Blok catch - obrađivač izuzetaka ima sljedeću sintaksu:

uhvatiti (T e) (...)

Klasa T specificirana u zaglavlju catch bloka mora pripadati klase izuzetaka. Blok catch sa formalnim argumentom e klase T ima potencijal da uhvati trenutni izuzetak te klase TE ako i samo ako je objekt te kompatibilan sa objektom e. Drugim riječima, potencijal hvatanja znači da je dodjela e = te važeća, što je moguće kada je klasa TE potomak klase T. Rukovalac čija je klasa T klasa izuzetaka je univerzalni rukovalac, potencijalno je u stanju uhvatiti bilo koji izuzetak jer su svi njegova djeca.

Potencijalnih osvajača može biti mnogo, samo je jedan isključen – onaj koji je prvi na listi za provjeru. Koja je procedura verifikacije? On je prilično prirodan. Rukovatelji se prvo provjeravaju redoslijedom kojim prate blok try, a prvi potencijalni hvatač postaje aktivan, hvata izuzetak i obrađuje ga. Iz ovoga postaje jasno da je redosled u listi blokova za hvatanje izuzetno važan. Većina dolazi prva specijalizovanih procesora, dalje kako se univerzalnost povećava. Dakle, prvo bi trebao postojati obrađivač izuzetaka DivideByZeroException, a zatim Main. Ako u njemu nema potencijalnog grabbera izuzetaka, tada će raditi standardni rukovalac, koji će prekinuti izvršavanje programa i izdati odgovarajuću poruku.

Hvatanje izuzetaka

Dok .NET Framework uključuje veliki broj predefiniranih klasa izuzetaka, postavlja se pitanje: kako ih koristiti u kodu za hvatanje stanja greške? Kako bi se pozabavili mogućim situacijama greške u C# kodu, program se obično dijeli na tri bloka različite vrste:

    Blokovi probaj enkapsulirati kod koji čini dio normalnih operacija programa koji potencijalno mogu naići na ozbiljne situacije greške.

    Blokovi uhvatiti enkapsulirati kod koji obrađuje situacije greške koje se javljaju unutar koda bloka try. Ovo je takođe pogodno mesto za evidentiranje grešaka.

    Blokovi konačno enkapsulirati kod koji čisti sve resurse ili izvodi druge radnje koje bi se inače radile na kraju pokušaja ili hvatanja blokova. Važno je shvatiti da se ovaj blok izvršava bez obzira na to da li je izbačen izuzetak ili ne.

Probaj i uhvati

Osnova rukovanja izuzetkom u C#-u je par ključnih riječi try and catch. Ove ključne riječi rade zajedno i ne mogu se koristiti odvojeno. Ispod je opšti oblik definicije try/catch blokova za rukovanje izuzecima:

try ( // Blok koda provjeren za greške. ) catch (ExcepType1 exOb) ( // Rukovalac iznimkama tipa ExcepType1. ) catch (ExcepType2 exOb) ( // Rukovalac iznimkama tipa ExcepType2. ) ...

gdje je ExcepType tip izuzetka koji se javlja. Kada naredba try izbaci izuzetak, hvata ga pridružena naredba catch, koja zatim obrađuje izuzetak. Ovisno o tipu izuzetka, izvršava se odgovarajući naredba catch. Dakle, ako se tipovi generiranog izuzetka i onoga specificiranog u naredbi catch poklapaju, onda se ovaj određeni izraz izvršava, a svi ostali se preskaču. Kada se uhvati izuzetak, varijabla izuzetka exOb dobija svoju vrijednost. U stvari, nije potrebno specificirati varijablu exOb. Stoga ga nije potrebno specificirati osim ako rukovaocu izuzetkom nije potreban pristup objektu izuzetka, što je prilično čest slučaj. Za rukovanje izuzetkom dovoljan je njegov tip.

Imajte na umu, međutim, da ako se ne izbaci iznimka, blok naredbe try završava normalno i sve njegove naredbe catch se preskaču. Izvršenje programa se nastavlja od prve naredbe koja slijedi nakon završne naredbe catch. Dakle, naredba catch se izvršava samo ako je izbačen izuzetak.

Pogledajmo primjer u kojem ćemo obraditi izuzetak koji se javlja prilikom dijeljenja broja sa 0:

Korišćenje sistema; koristeći System.Collections.Generic; koristeći System.Linq; koristeći System.Text; imenski prostor ConsoleApplication1 ( klasa Program ( static int MyDel(int x, int y) ( return x / y; ) static void Main() ( probajte ( Console.Write("Enter x: "); int x = int.Parse(Console .ReadLine()); Console.Write("Unesite y: "); int y = int.Parse(Console.ReadLine()); int rezultat = MyDel(x, y); Console.WriteLine("Rezultat: " + rezultat); ) // Rukovanje izuzetkom koji se javlja prilikom dijeljenja sa nultim ulovom (DivideByZeroException) ( Console.WriteLine("Detektovana podjela sa 0!!!\n"); Main(); ) // Rukovanje iznimkom kada je broj broj. je pogrešno unesen u hvatanje konzole (FormatException) ( Console.WriteLine("Ovo NIJE broj!!!\n"); Main(); ) Console.ReadLine(); ) ) )

Ovaj jednostavan primjer jasno ilustruje rukovanje izuzetkom prilikom dijeljenja sa 0 (DivideByZeroException), kao i korisničku grešku prilikom unosa ne-broja (FormatException).

Posljedice nehvatanja izuzetaka

Hvatanje jednog od standardnih izuzetaka, kao u gornjem primjeru, ima još jednu prednost: eliminira crash programe. Jednom kada se izbaci izuzetak, mora ga uhvatiti neki dio koda na određenoj lokaciji u programu. Uopšteno govoreći, ako izuzetak nije uhvaćen u programu, onda će ga uhvatiti runtime sistem. Ali poenta je da će izvršni sistem izdati poruku o grešci i prekinuti izvršavanje programa.

Izuzetak je instanca klase koja je naslijeđena i eksplicitno i implicitno iz osnovne klase System.Exception.

Varijable deklarirane u bloku try izlaze izvan opsega kada se kontrola proslijedi bloku catch ili finally. Na kraju bloka try, čak i ako se ništa nije dogodilo (nije se dogodila greška), kontrola se automatski prenosi na finally blok, koji mora sadržavati upute za oslobađanje resursa.

Kada se otkrije greška, kod izbacuje izuzetak (kreira instancu klase izuzetka) i izdaje ga na sljedeći način:

Throw new IndexOutOfRangeException("Uneli ste: " + userInput);

Čim prevodilac naiđe na naredbu throw unutar bloka try, odmah traži odgovarajući blok catch.

Izrazi Throw ne moraju biti u istoj metodi kao i blok try; blok try nastavlja raditi čak i ako je kontrola proslijeđena drugim metodama.

Izraz throw može biti u bilo kojoj metodi pozvanoj tokom izvođenja bloka try - ne mora biti u istoj metodi u kojoj je definiran blok try

Rukovaoci izuzecima za izvedenu klasu (IndexOutOfRangeException) moraju ići ispred onih za osnovnu klasu (Exception) (!)

Ako je obrađivač catch napisan kao: catch (…), to znači da je odgovoran za bilo koji kod (za svaki izuzetak koji se dogodi), uključujući i one koji nisu napisani u C# ili kojima se ne upravlja.

C# je zahtjev da se samo instance klase izvedene iz System.Exception mogu proslijediti kao izuzeci.

Dok(tačno) // beskrajni ciklus( Console.Write("Izaberite stavku menija od 0 do 5 ili za izlaz: "); string userInput = Console.ReadLine(); if (userInput == "") (Console.WriteLine("Pritisli ste izlaz... "); prekid; ) pokušaj ( int x = int.Parse(userInput); switch (x) (slučaj 0: Console.WriteLine("Item 0 selected"); break; case 1: Console.WriteLine("Item 1 selected "); prekid; slučaj 2: Console.WriteLine("Item 2 selected"); break; case 3: Console.WriteLine("Item 3 selected"); break; case 4: Console.WriteLine("Item 4 selected") ; break; case 5: Console.WriteLine("Item 5 is selected"); break; default: throw new IndexOutOfRangeException(); break; ) ) catch (IndexOutOfRangeException e) ( Console.WriteLine("Invalid value. Odaberite cifru iz ") ; ) catch (FormatException e) ( Console.WriteLine("Greška pri konverziji, možda ste uneli string..."); ) catch (Izuzetak e) ( Console.WriteLine("Još jedna greška"); ) catch ( ) // rukujemo neupravljanim kodom i kodom na drugom jeziku)

Svojstva i metode System.Exception

if (ErrorCondition == true) (Exception myException = new ClassMyException("Pomoć!"); myException.Source = "Naziv aplikacije"; myException.HelpLink = "myHelpFile.txt"; izbaci myException; )

Kod ne treba da izbaci izuzetke iz opšte klase System.Exception - ne daje nikakvu ideju o prirodi stanja greške (!). Postoje dvije važne klase u hijerarhiji:

SystemException - Namijenjen za izuzetke koje obično izaziva .NET runtime, ili izuzetke koji su opće prirode i mogu ih izbaciti gotovo svaka aplikacija. Potklasa predstavlja i fatalne i nefatalne greške.

ApplicationException - je baza namijenjena za bilo koju klasu izuzetaka definiranih od strane trećih strana.

IOException (System.IO namespace) su povezani sa čitanjem i pisanjem podataka u datoteku.

StackOverflowException se događa kada se memorija dodijeljena steku popuni do kapaciteta. Do prelivanja steka može doći, na primjer, kada metoda počne rekurzivno pozivati ​​samu sebe. Uobičajeni uzrok EndOfStreamExceptiona je pokušaj čitanja izvan granica datoteke. Izuzetak OverflowException se događa, na primjer, kada pokušavate baciti int koji sadrži -40 na uint u provjerenom kontekstu.

Ugniježđeni pokušaji se koriste iz dva razloga:

— kako bi se promijenio tip generiranog izuzetka (koristeći svojstvo InnerException, koje sadrži referencu na bilo koji generirani izuzetak);

— rukovanje različitim izuzecima u različitim dijelovima koda.

Definiranje vlastitih klasa izuzetaka

Definiranje vlastitih izuzetaka je prilično jednostavan zadatak, jer... rijetko im morate dodati vlastite metode. Potrebno je samo implementirati konstruktor kako bi se osiguralo da je konstruktor osnovne klase ispravno pozvan.

Klasa LandLineSpyFoundException: ApplicationException (javna LandLineSpyFoundException(string spyName) : base("spyName"+spyName) ( ) public LandLineSpyFoundException(string spyName, Exception innerException) : base(spyName, innerException) ( ) )

Dobar dan! Danas ćemo govoriti o tome kako postupati s greškama u programima napisanim na C#.

Želio bih odmah napomenuti da se greške u programima mogu podijeliti u dvije grupe: greške u vremenu sastavljanja programa (u fazi kompilacije) i greške u izvođenju programa. Ovaj vodič će govoriti o greškama u toku izvođenja!

Prisjetimo se primjera iz prethodne lekcije, gdje je korisnik morao da unese dva cijela broja sa tastature. Zatim sam također tražio da unesem brojeve i cijele brojeve. Zašto? Prije jer ako u taj program unesete ne broj, već samo tekst, ili ne cijeli, već razlomak, onda će doći do greške u izvođenju! Iz tog razloga vam danas govorim o mehanizmima i principima rukovanja greškama u programima.

I tako, ako sumnjamo da naš program može imati greške u izvođenju, na primjer, zbog činjenice da je korisnik unio pogrešne podatke, moramo se pobrinuti za rukovanje tim greškama. Pristup obradi slične situacije je slijedeći pravila: označen je blok koda čije izvršavanje može uzrokovati greške; dodjeljuje se blok koda koji je odgovoran za obradu grešaka koje su se dogodile.

Naznačen je blok koda u kojem se mogu pojaviti greške ključna riječ probaj praćeno proteze(koji potencijalno sadrže opasnim operacijama). Neposredno nakon takvog bloka trebao bi biti blok za obradu grešaka, koji se označava ključnom riječi uhvatiti, a u zagradama iza ove riječi, vrsta grešaka koje blok podataka obrađuje nakon zatvaranja zagrada, zatim kovrdžave, u okviru kojih se provodi obrada. Šematski, to izgleda ovako:

Pokušajte ( // Potencijalno opasan blok koda ) catch ( error_type ) ( // Rukovanje greškom ) // Dalji programski izrazi

I radi ovako ako je u bloku probaj, nije došlo do greške, a zatim blokirajte uhvatiti se ne izvršava, već se kontrola prenosi, tj. sljedeći blok se izvršava uhvatiti operater. Ali ako je unutar bloka probaj dođe do greške, izvršenje ovog bloka se prekida i kontrola se prenosi na blok uhvatiti, a tek tada se izvršavaju operatori koji slijede ovaj blok.

U praksi, nakon jednog bloka probaj, može biti nekoliko blokova uhvatiti, za odvojeno rukovanje greškama različitih tipova.

Izmijenimo programski kod iz prethodne lekcije, dodamo kontrolu i rukovanje greškama koje mogu nastati kada korisnik unese netačne podatke.

//Potencijalno opasan pokušaj blokiranja ( //Zatražite od korisnika da unese prvi broj Console.Write("Unesite prvi broj i pritisnite Enter ključ: "); //Dobijanje stringa prvog reda firstString = Console.ReadLine(); //Pretvaranje prvog retka u broj int firstArg = Convert.ToInt32(firstString); //Traženje od korisnika da unese drugi broj Console. Write("Unesite prvi broj i pritisnite tipku Enter: "); //Dobijanje niza drugog reda secondString = Console.ReadLine(); //Pretvaranje drugog retka u broj int secondArg = Convert.ToInt32(secondString); //Dodavanje dvije varijable int result = firstArg + secondArg ; //Izlaz rezultata Console.WriteLine("Rezultat zbrajanja unesenih brojeva: " + result.ToString()); ) //Blok rukovanja greškom, SystemException - najviše uobičajen tip hvatanja grešaka (SystemException) ( Console.WriteLine("Tokom izvođenja došlo je do greške programa, vjerovatno su uneseni netačni podaci!"); )

Sada, ako korisnik unese netačne podatke umjesto cijelog broja, greška koja se pojavi će biti obrađena. Ako zalijepite ovaj kod u " glavni", izgradite i pokrenite program, vidjet ćete sljedeće ponašanje:

I tako, u ovoj lekciji je to predstavljeno Osnovne informacije u vezi sa mehanizmom za rukovanje greškama (situacije izuzetaka) u C# jeziku. U sljedećoj lekciji ćemo govoriti o kreiranju i korištenju vlastitih metoda (funkcija), a više puta ćemo se vraćati na temu rukovanja greškama!

Najbolji članci na ovu temu