7/27/2019 curs .NET 5.pdf
1/23
Exceptii
O linie de cod poate sa nu se execute corect din diverse motive: depasire aritmetica,
depasire stiva, memorie insuficienta, indici in afara intervalului, etc.O aplicatie ce si-ar propune sa verifice toate (sau aproape toate) posibilitatile ce pot
aparea in executarea unei linii de cod si-ar pierde din claritate, ar fi foarte greu deintretinut, iar mare parte din timp procesor s-ar consuma cu aceste verificari.
Realizarea unei astfel de aplicatii este aproape imposibila.Folosind exceptiile nu este nevoie sa scriem cod pentru a detecta toate aceste posibile
caderi. In plus codul se executa mai rapid.
Trebuie spus de la inceput ca exceptiile genereaza alte probleme care trebuiesc rezolvate.
Dintre avantajele introducerii exceptiilor amintim :
abilitatea de a mentine cod clar si de a intelege logica aplicatiei mai usor;
posibilitatea de a detecta si localiza bug-uri in cod;Cand apare o cadere, CLR scaneaza stiva firului cautind codul ce ar putea trata
exceptia. Daca nu exista un asemenea cod, primim o notificare unhandled exception.Folosirea incorecta a tratarii execeptiilor poate crea neplaceri mai mari decat nefolosirea
lor.
Evolutia manipularii exceptiilor
Win32 API si COM nu folosesc exceptiile pentru a notifica utilizatorul despre problema
aparuta. Multe functii returneaza FALSE sau NULL sau o valoare de tip HRESULT
pentru a indica ca ceva nu s-a executat corect. De altfel nu s-a standardizat tratareaerorilor in Win32 API. La inceput C si C++ nu suportau exceptiile.
Metoda veche de raportare a erorilor se limita la un numar pe 32 de biti. In marea
majoritate a cazurilor mesajele nu sunt clare si nu ofera suficienta informatie pentru adetecta ce anume s-a intimplat.
Din acest punct de vedere mecanismul de manipulare al exceptiilor ofera mai multe
avantaje:O exceptie include un sir de caractere ce o descrie.
Sirul de caractere contine o cale catre apelul ce a declansat anomalia. Informatiile se
gasesc pe stiva.
Exceptiile nu pot fi ignorate.
Daca o metoda arunca o exceptie, aceasta inseamna ca nu lucreaza asa cum ar trebui.Daca aplicatia nu trateaza exceptia, CLR termina aplicatia.
Toate metodele definite de tipurile din cadrul de lucru .NET arunca exceptii pentru aindica ca anumite presupuneri au fost incalcate. Nu se returneaza nici o valoare de stare.
7/27/2019 curs .NET 5.pdf
2/23
Mecanica manipularii exceptiilor
Mecanismul de manipulare al exceptiilor cadrului de lucru .NET este construit folosind
Structured Exception Handling (SEH).
Urmatorul cod C# arata o folosire standard a mecanismului de tratare al exceptiilor.
void SomeMethod()
{
try
{
// aici scriem codul ce vrem sa-l protejam (supus verificarii)
}
catch (InvalidCastException)
{
// Aici este codul ce se va executa daca apare exceptia
// InvalidCastException sau orice exceptie a unui
// tip derivat din InvalidCastException.
}
catch (NullReferenceException)
{
// Aici este codul ce se va executa daca apare exceptia
// NullReferenceException sau orice exceptie a unui
// tip derivat din NullReferenceException.
}
catch (Exception e)
{
// In interiorul acestui bloc scriem codul care se executa
// pentru o exceptie CLS-compliant (conforma cu CLS).
// In mod normal se rearunca exceptia.
throw;
}catch
{
// Aici este codul ce se va executa pentru price tip de exceptie
// In mod normal se rearunca exceptia.
throw;
}
finally
{
// Acest cod este garantat ca se executa totdeauna, dar
// binenteles exista cateva exceptii de la aceasta presupunere.
// Codul de aici se executa indiferent daca a aparut
// sau nu o exceptie.
// Este asa numitul cod de curatare, mai precis de terminare
// a unor operatii incepute in bocul try.
}
//
// In continuare este codul ce se executa cand nu// a aparut nici o exceptie.
}
7/27/2019 curs .NET 5.pdf
3/23
In mod normal in cod avem un bloctry, unul sau mai multe blocuricatch si optional
un blocfinally.
Exemplu:
using System;//includes System.Exception
class ExceptionApp
{
public TestMethod( int i, int j)
{
try
{
...
...
// Functia apelata poate arunca o exceptie.
ExceptionMethod(); //*1
...
...
int k=0;
// Operatiile pot arunca exceptii
// Daca j = 0 atunci avem impartire la zero
k = i/j; //*2
...
...
//Constient, se arunca o exceptie, ce tine de logica aplicatiei
if( k == 0)
throw new Exception(); //*3
}
catch (Exception e) //*4 se prind toate exceptiile
{
}
Console.Writeline("Code after exception"); // *5
}
}
Blocul try
In general un bloc try contine cod ce are nevoie de operatii de terminare corecta(curatare) sau operatii de tratare a exceptiilor.
Codul pentru terminare corecta (de ex. inchiderea unui fisier) trebuie plasat in blocul
finally.Codul de tratare al exceptiilor trebuie plasat in unul sau mai multe blocuri catch. Fiecare
bloc catch identifica un anumit tip de exceptie.
7/27/2019 curs .NET 5.pdf
4/23
Putem crea cate un bloc catch pentru orice tip de eveniment pentru care avem
posibilitatea de a corecta exceptia aparuta sau a obtine mai multe informatii despreaceasta. Aceste informatii pot ajuta pentru depistarea unui bug sau neindeplinirea unor
conditii de sistem (de ex. adresa IP).
Un bloc try trebuie sa fie asociat cu cel putin un bloc catch sau finally.
Blocul catch
Blocul catch contine cod ce se executa cand apare o exceptie. Daca codul din blocul try
nu cauzeaza o exceptie, atunci codul din blocul catch nu se executa. Daca exista bloculfinally atunci codul se executa indiferent daca s-a aruncat sau nu o exceptie. Daca nu a
aparut o exceptie atunci executia continua cu codul de dupa blocul finally.
Expresia dintre paranteze de la blocul catch se numeste filtru exceptie.Exceptia filtru este un tip ce reprezinta o situatie exceptionala pe care dezvoltatorul a
anticipat-o si poate sa o trateze intr-un anume fel (poate iesi din aceasta situatie).
In C#, tipul din filtru trebuie sa fie System.Exception sau un tip derivat din
System.Exception.
Blocurile catch sunt tratate in mod secvential, de sus in jos, deci blocurile catch pentru
tratarea exceptiilor specifice trebuie plasate cat mai aproape de blocul try.
Daca o exceptie este aruncata de codul din blocul try (sau orice metoda apelata din cadrulacestuia), CLR cauta blocurile catch al caror filtru se potriveste cu exceptia aruncata.
Daca nu exista un asemenea bloc catch, atunci CLR cauta in stiva un bloc catch al carui
filtru se potriveste. Daca cautarea s-a terminat si nu s-a gasit un asemenea bloc atunciCLR opreste aplicatia si afiseaza mesajul Unhandled exception.
CLR pastreaza o arborescenta a tuturor metodelor apelate din blocul try.
Cand s-a localizat un bloc catch ce trateaza excepia (filtrul se potriveste), CLR executacodul din toate blocurile finally, plecand de la acela al blocului try ce a generat exceptia
si oprindu-se la acela al blocului try ce contine blocul catch ce trateaza exceptia.
Codul din ultimul bloc finally se va executa dupa ce s-a executat codul din blocul catch.
In C#, un filtru catch poate specifica o variabila de tip exceptie. Aceasta variabila se
refera la un obiect derivat din System.Exception ce a aruncat aceasta exceptie. Codul din
blocul catch poate referi aceasta variabila pentru a obtine informatii suplimentare despreexceptie.
La sfarsitul ultimului bloc catch avem urmatoarele posibilitati:
1. rearuncarea aceleasi exceptii;2. aruncarea unei alte exceptii;3. sa lasam ca firul sa termine cautarea aici.
In primele doua situatii, CLR va cauta in continuare pe stiva un bloc catch ce poate trata
exceptia.
7/27/2019 curs .NET 5.pdf
5/23
In ultima situatie se va executa codul din blocul finally si apoi se continua in secventa cu
codul ce urmeaza acestui bloc. Daca nu exista un bloc finally, se continua executia cucodul ce urmeaza ultimului bloc catch.
Blocul finally
Un bloc finally contine cod ce este garantat ( ?!) ca se va executa.
Exemplu:
void ReadData(String pathname)
{
FileStream fs = null;
try
{
fs = new FileStream(pathname, FileMode.Open);
// Procesare date din fisier
}
catch (OverflowException){
// Inside this catch block is where you put code that recovers
// from an OverflowException (or any exception type derived
// from OverflowException).
}
finally
{
// Make sure that the file gets closed.
if (fs != null) fs.Close();
}
}
Indiferent de cum se executa codul din blocul try, codul din blocul finally se va executa.Blocul finally trebuie sa apara dupa toate blocurile catch asociate cu blocul try.
Nu se arunca exceptii in blocul finally.
Riscul este de a construi o aplicatie ce nu se mai termina.
Ce este o exceptie?
Termenul eroare indica ca programatorul a facut ceva gresit.
Exceptiile nu indica neaparat o eroare in cod.
Exceptiile nu conduc neaparat la oprirea executiei unei aplicatii.
O exceptie poate fi definita ca fiind violarea unei presupuneri implicite asupra unei
interfete (J. Richter).
De exemplu construirea unui tip nu poate cuprinde toate situatiile in care acesta poate fi
folosit. Cazurile care nu sunt implementate dar se incearca a fi folosite vor arunca
anumite exceptii in ideea de a nu folosi tipul respectiv altfel decat a fost proiectat.
7/27/2019 curs .NET 5.pdf
6/23
Trebuie sa facem distinctie intre exceptiile aruncate de aplicatie si cele aruncate de CLR.Comportarile aplicatiei sunt diferite functie de cine a aruncat exceptia.
CLR arunca exceptii, de ex. System.StackOverflowException, sau
System.OutOfMemoryException, sau System.ExecutionEngineException.
In aceste situatii este posibil ca codul din blocul finally sa nu se poata executa.
OutOfMemoryException = este aruncata aceasta exceptie cand construim un nou obiect
si nu exista memorie suficienta. In acest caz procesul se termina imediat, codul din bloculfinally se executa. Daca exceptia este aruncata de CLR atunci procesul se termina imediat
si aplicatia nu mai este in stare sa prinda aceasta exceptie si blocul finally nu se mai
executa.
StackOverflowException = CLR arunca aceasta exceptie cand unfir a utilizat tot spatiul
pentru stiva. Aplicatia poate prinde aceasta exceptie dar codul din blocul finally nu se vaexecuta pentru ca si asta are nevoie de spatiu pe stiva.Fiecare bloc catch ce prinde aceasta exceptie trebuie sa o arunce in continuare (rethrow)
pentru a da sansa CLR-ului sa termine procesul.
Daca exceptia apare in CLR, aplicatia nu poate prinde aceasta exceptie si blocul finallynu se executa. In acest caz CLR termina procesul sau lanseaza un debugger.
ExecutionEngineException = CLR arunca aceasta exceptie cand detecteaza ca structurile
sale de date interne sunt corupte sau are anumite bug-uri. CLR-ul termina procesul sau valansa un debugger pentru proces. Nu se executa nici un bloc catch si nici finally.
Clasa System.Exception
Modelul de tratare al exceptiilor este bazat pe reprezentarea exceptiilor ca obiecte sisepararea codului aplicatiei de codul de tratatre al exceptiilor.
Un bloc catch ce trateaza System.Exception trebuie sa fie ultimul bloc pentru try.
Ordinea blocurilor catch ce trateaza o exceptie va fi urmatoarea : intai exceptia pentru
tipul derivat si apoi exceptia pentru clasa de baza (blocurile catch se trateaza secvential,
iar cautarea se opreste dupa primul bloc catch ce trateaza exceptia).
Exemplu (cod incorect al doilea bloc catch nu va fi executat niciodata pentru ca
System.Web.HttpException este derivat din System.Exception).try{// Code which can cause a web exception or arithmetic exception.}catch (System.Exception ex){
MessageBox.Show ( "An exception occurred." );}catch (System.Web.HttpException ex)
7/27/2019 curs .NET 5.pdf
7/23
{MessageBox.Show ( "A web exception occurred." );
}
Acelasi exemplu, dar de aceasta data corect:
try{// Code which can cause a web exception or arithmetic exception.}catch (System.Web.HttpException ex){
MessageBox.Show ( "A web exception occurred." );}catch(System.Exception ex){
MessageBox.Show ( "An exception occurred." );}
In clasa Exception exista doua categorii de exceptii:
clase exceptii predefinite de CLR, derivate din SystemException.
Clase exceptii definite de utilizator la nivel de aplicatie si derivate din
ApplicationException.
CLR permite o instanta de orice tip sa fie aruncata pentru o exceptie.
Tipurile de exceptii ce sunt derivate din System.Exception se numesc CLS-compliant(conforme cu CLS).
Tipul System.Exception este descris in continuare.
Message - Read-only String Indica de ce a fost aruncata exceptia.
Source - Read/write String Contine numele assembly ce a generat exceptia.
StackTrace - Read-only String Contine numele si signatura metodei apelate ce a dus la
aruncarea exceptiei.
TargetSite - Read-only MethodBase Contine metoda ce a generat exceptia.
HelpLink - Read-only String Contine un URL la documentatia exceptiei.
InnerException - Read-only Exception Indica exceptia anterioara daca exceptia
curenta a fost generata in timp ce manipula o alta exceptie.
Metoda GetBaseException returneaza originea exceptiei.
HResult - Read/write Int32 Proprietate protected, folosita cand exista cod managed siunmanaged COM.
7/27/2019 curs .NET 5.pdf
8/23
Cateva clase pentru exceptii definite in FCL.
Class Description
AppDomainUnloadedException The exception that is thrown when
an attempt is made to access an
unloaded application domain.
ApplicationException The exception that is thrown when
a non-fatal application error
occurs.
ArgumentException The exception that is thrown when
one of the arguments provided to a
method is not valid.
ArgumentNullException The exception that is thrown when
a null reference is passed to a
method that does not accept it as
a valid argument.
ArgumentOutOfRangeException The exception that is thrown when
the value of an argument is
outside the allowable range of
values as defined by the invoked
method.
ArithmeticException The exception that is thrown for
errors in an arithmetic, casting, or
conversion operation.
ArrayTypeMismatchException The exception that is thrown when
an attempt is made to store an
element of the wrong type within
an array.
7/27/2019 curs .NET 5.pdf
9/23
BadImageFormatException The exception that is thrown when
the file image of a DLL or an
executable program is invalid.
CannotUnloadAppDomainException The exception that is thrown when
an attempt to unload an
application domain fails.
ContextMarshalException The exception that is thrown when
an attempt to marshal an object
across a context boundary fails.
DivideByZeroException The exception that is thrown when
there is an attempt to divide an
integral or decimal value by zero.
DllNotFoundException The exception that is thrown when
a DLL specified in a DLL import
cannot be found.
DuplicateWaitObjectException The exception that is thrown when
an object appears more than once
in an array of synchronization
objects.
EntryPointNotFoundException The exception that is thrown when
an attempt to load a class fails due
to the absence of an entry method.
Exception Defines the base class for all
exceptions.
ExecutionEngineException The exception that is thrown when
there is an internal error in the
execution engine of the common
7/27/2019 curs .NET 5.pdf
10/23
language runtime. This class
cannot be inherited.
FieldAccessException The exception that is thrown whenthere is an illegal attempt to
access a private or protected field
inside a class.
FormatException The exception that is thrown when
the format of an argument does
not meet the parameter
specifications of the invoked
method.
IndexOutOfRangeException The exception that is thrown when
an attempt is made to access an
element of an array with an index
that is outside the bounds of the
array. This class cannot be
inherited.
InvalidOperationException The exception that is thrown when
a method call is invalid for the
object's current state.
InvalidProgramException The exception that is thrown when
a program contains an invalid IL or
metadata. Generally this indicates
a bug in a compiler.
MemberAccessException The exception that is thrown when
an attempt to access a class
member fails.
7/27/2019 curs .NET 5.pdf
11/23
MethodAccessException The exception that is thrown when
there is an illegal attempt to
access a private or protected
method inside a class.
MissingFieldException The exception that is thrown when
there is an attempt to dynamically
access a field that does not exist.
MissingMemberException The exception that is thrown when
there is an attempt to dynamically
access a class member that does
not exist.
MissingMethodException The exception that is thrown when
there is an attempt to dynamically
access a method that does not
exist.
MulticastNotSupportedException The exception that is thrown when
there is an attempt to combine two
instances of a non-combinable
delegate type unless one of the
operands is a null reference. This
class cannot be inherited.
NotFiniteNumberException The exception that is thrown when
a floating-point value is positive
infinity, negative infinity, or Not-a-
Number (NaN).
NotImplementedException The exception that is thrown when
a requested method or operation is
not implemented.
7/27/2019 curs .NET 5.pdf
12/23
NotSupportedException The exception that is thrown when
an invoked method is not
supported, or when there is an
attempt to read, seek, or write to a
stream that does not support the
invoked functionality.
NullReferenceException The exception that is thrown when
there is an attempt to dereference
a null object reference.
ObjectDisposedException [To be supplied by Microsoft.]
OutOfMemoryException The exception that is thrown when
there is not enough memory to
continue the execution of a
program.
OverflowException The exception that is thrown when
an arithmetic, casting, or
conversion operation in a checked
context results in an overflow.
PlatformNotSupportedException The exception that is thrown when
a feature does not run on a
particular platform.
RankException The exception that is thrown when
an array with the wrong number of
dimensions is passed to a method.
StackOverflowException The exception that is thrown when
the execution stack overflows by
having too many pending method
calls. This class cannot be
7/27/2019 curs .NET 5.pdf
13/23
inherited.
SystemException Defines the base class forpredefined exceptions in the
System namespace.
TypeInitializationException The exception that is thrown as a
wrapper around the exception
thrown by the class initializer. This
class cannot be inherited.
TypeLoadException The exception that is thrown when
type-loading failures occur.
TypeUnloadedException The exception that is thrown when
there is an attempt to access an
unloaded class.
UnauthorizedAccessException The exception that is thrown when
the operating system deniesaccess for reasons involving an IO
error and some kinds of security
errors.
UriFormatException The exception that is thrown when
an invalid Uniform Resource
Identifier (URI) is detected.
ApplicationException este aruncata de un program al utilizatorului si nu de CLR. In
mod normal exceptiile create de utilizator ar trebui derivate din acest tip.
ApplicationException diferentiaza exceptiile definite de utilizator decele definite de
sistem.
ApplicationException nu furnizeaza informatii despre cauza exceptiei.
7/27/2019 curs .NET 5.pdf
14/23
In mod normal nu se arunca o asemenea exceptie de catre aplicatie, dar in cazul cand se
face acest lucru se va pasa constructorului clasei un mesaj ce va descrie cauza aparitieiexceptiei.
Descrierea membrilor clasei conform documentatiei Microsoft este urmatoarea:
!"
#$%"&'"
%"&
'
()%"&
')
%"& '"*
%"& ')""
)%"&'
+%"&
,*
+
'-%"&
./"+
'#%"&
""/"))
'*,%"&
./
!""
'%"&
'"
)%"& )"
7/27/2019 curs .NET 5.pdf
15/23
!"
#0%"& '#01$/)"
!%"&
*"""))
233/"!)
(
Clasa SystemException derivata din Exception
!"
#$%"&'"
%"&
'
()%"&
')
%"& '"*
%"&')""
)%"&
'
+%"&
,*+
'-%"&./"+
7/27/2019 curs .NET 5.pdf
16/23
'#%"&
""/"))
'*,%"& ./!""
'%"&
'"
)%"&
)"
!"
#0%"&'#01$/)"
!%"&
*"""))
233/"!)
(%"&
"*
Clase exceptii des utilizate
System.ArithmeticException exceptii ce apar in timpul operatiilor aritmetice, cum ar fi
System.DivideByZeroException and System.OverflowException.
System.ArrayTypeMismatchException - ArrayTypeMismatchException este aruncata
cand un obiect incompatibil se incearca a fi memorat intr-un Array.
System.DivideByZeroException incercare de impartire prin zero.
System.IndexOutOfRangeException - IndexOutOfRangeException este aruncata cand se
7/27/2019 curs .NET 5.pdf
17/23
incearca sa se acceseze un tablou folosind un index mai mic ca zero sau in afara
intervalului tabloului.
System.InvalidCastException aruncata cand o conversie implicita de la tipul de baza sau
interfata la tipul derivat nu se executa corect in momentul executiei.
System.NullReferenceException aruncata cand se foloseste o referinta null la un obiect
pentru a-l accesa.
System.OutOfMemoryException - OutOfMemoryException este aruncata cand operatia
'new' (crearea unui nou obiect) nu se executa cu succes pentru ca nu exista suficientamemorie.
System.OverflowException - OverflowException este aruncata cand apare depasire la
executia unei operatii aritmetice.
System.StackOverflowException - StackOverflowException este aruncata cand cand stiva
de executie este prea mica pentru a executa toate apelurile initiate (probabil buclainfinita).
ArgumentException exceptie aruncata cand un argument furnizat unei metode este
invalid.
CLR arunca exceptii pentru tipurile derivate din SystemException.
O parte dintre aceste exceptii nu semnaleaza situatii fatale, o alta parte da.
Metodele definite de tipurile din FCL sunt presupuse ca arunca exceptii derivate din
System.Exception.
Exemplu:
using System;
public class MyClass {}
public class ArgExceptionExample {
public static void Main() {
MyClass my = new MyClass();
string s = "sometext";
try {
int i = s.CompareTo(my);
}
catch (Exception e) {
Console.WriteLine("Error: {0}",e.ToString());
}
}
}
Iesirea este:
Error: System.ArgumentException: Object must be of type String.
at System.String.CompareTo(Object value)
at ArgExceptionExample.Main()
7/27/2019 curs .NET 5.pdf
18/23
Definirea claselor de exceptii
Prin conventie numele unui tip exceptie ar trebui sa se termine cu Exception.
Metodele ar trebui sa-si verifice argumentele inainte de a le folosi.
Clasele din FCL ce pot fi folosite pentru acest lucru sunt: ArgumentNullException,
ArgumentOutOfRangeException
DuplicateWaitObjectException.
Nu se va scrie cod ce va arunca o exceptie de tipul Exception, ApplicationException, sau
SystemException.
Exemplu:
class SomeType
{
public void SomeMethod(Object o)
{
if (!((o is ICloneable) && (o is IComparable)))
throw new LipsaInterfataException(...);
// urmeaza cod
}
}
Aici avem tipul LipsaInterfataException. Cum il definim?
Singura regula de care trebuie sa tinem seama este cea referitoare la efectele colaterale.
Daca derivam aceasta exceptie din ArgumentException, atunci codul existent cecapteaza aceasta exceptie va capta si noua exceptie.
Cand definim acest tip trebuie sa vedem cu cine se aseamana dintre exceptiile existente,asemanare in sensul metodei de tratare a exceptiei.Daca derivam tipul din Exception nu exista prea multe informatii despre exceptia
aruncata.
Cel mai indicat este sa ne gandim la efectele colaterale decat la cele directe cand derivamun tip exceptie.
Clasa de baza Exception defineste trei constructori:
1. unul implicit ce seteaza toate campurile si proprietatile la valori implicite;2. un ctor cu un parametru de tip String ce creaza o instanta a tipului si seteaza un
mesaj specific.
3. un ctor cu doi parametri: un String si o instanta a unui tip derivat din Exception ceseteaza un mesaj si o exceptie interna.
Daca adaugam campuri la un tip exceptie acestia trebuiesc initializati in constructor.
ExempluAruncarea si tratarea unei exceptii ce face referinta la inner Exception.using System;
public class MyAppException:ApplicationException
7/27/2019 curs .NET 5.pdf
19/23
{
public MyAppException (String message) : base (message) {}
public MyAppException (String message, Exception inner) :
base(message,inner) {}
}
public class ExceptExample
{
public void ThrowInner ()
{
throw new MyAppException("ExceptExample inner exception");
}
public void CatchInner()
{
try
{
this.ThrowInner();
}
catch (Exception e)
{
throw new MyAppException("Error caused by tryingThrowInner.",e);
}
}
}
public class Test
{
public static void Main()
{
ExceptExample testInstance = new ExceptExample();
try
{
testInstance.CatchInner();
}
catch(Exception e)
{
Console.WriteLine ("In Main catch block. Caught: {0}",
e.Message);
Console.WriteLine ("Inner Exception is {0}",e.InnerException);
}
}
}
Iesirea este:In Main catch block. Caught: Error caused by trying ThrowInner.
Inner Exception is MyAppException: ExceptExample inner exception
at ExceptExample.ThrowInner()
at ExceptExample.CatchInner()
Exemplu (2) de definire a unei exceptii
using System;
using System.IO;
7/27/2019 curs .NET 5.pdf
20/23
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;
// Allow instances of DiskFullException to be serialized.
[Serializable]
sealed class DiskFullException : Exception, ISerializable
{
// The three public constructors
public DiskFullException()
: base()
{ // Call base constructor. }
public DiskFullException(String message)
: base(message)
{ // Call base constructor. }
public DiskFullException(String message, Exception innerException)
: base(message, innerException)
{ // Call base constructor. }
// Define a private field.
private String diskpath;
// Define a read-only property that returns the field.
public String DiskPath { get { return diskpath; } }
// Override the public Message property so that the
// field is included in the message.
public override String Message
{
get
{
String msg = base.Message;
if (diskpath != null)
msg += Environment.NewLine + "Disk Path: " + diskpath;
return msg;
}
}
// Because at least one field is defined, define the
// special deserialization constructor. Because this
// class is sealed, this constructor is private. If this
// class is not sealed, this constructor should be protected.
private DiskFullException(SerializationInfo info,
StreamingContext context)
: base(info, context)
{ // Let the base deserialize its fields.
// Deserialize each field.
diskpath = info.GetString("DiskPath");}
// Because at least one field is defined,
// define the serialization method.
void ISerializable.GetObjectData(SerializationInfo info,
StreamingContext context)
{
// Serialize each field.
7/27/2019 curs .NET 5.pdf
21/23
info.AddValue("DiskPath", diskpath);
// Let the base type serialize its fields.
base.GetObjectData(info, context);
}
// Define additional constructors that set the field.
public DiskFullException(String message, String diskpath)
: this(message) { // Call another constructor.
this.diskpath = diskpath;
}
public DiskFullException(String message, String diskpath,
Exception innerException)
: this(message, innerException) { // Call another constructor.
this.diskpath = diskpath;
}
}
// The following code tests the serialization of the exception.
class App {
static void Main() {
// Construct a DiskFullException object, and serialize it.DiskFullException e =
new DiskFullException("The disk volume is full", @"C:\");
FileStream fs = new FileStream(@"Test", FileMode.Create);
IFormatter f = new SoapFormatter();
f.Serialize(fs, e);
fs.Close();
// Deserialize the DiskFullException object, and check its fields.
fs = new FileStream(@"Test", FileMode.Open);
e = (DiskFullException) f.Deserialize(fs);
fs.Close();
Console.WriteLine("Type: {1}{0}DiskPath: {2}{0}Message: {3}",
Environment.NewLine, e.GetType(), e.DiskPath, e.Message);
}
}
Un cod corect de serializare (fisierul nu ramine intr-o stare incorecta, se aduce la starea
de dinanintea aparitiei exceptiei):
public void SerializeObjectGraph(FileStream fs,
IFormatter formatter, Object rootObj) {
// Save the current position of the file.
Int64 beforeSerialization = fs.Position;
try {
// Attempt to serialize the object graph to the file.
formatter.Serialize(fs, rootObj);
}catch { // Catch all CLS and non-CLS exceptions.
// If ANYTHING goes wrong, reset the file back to a good state.
fs.Position = beforeSerialization;
// Truncate the file.
fs.SetLength(fs.Position);
// NOTE: The preceding code isnt in a finally block because
// the stream should be reset only when serialization fails.
// Let the caller(s) know what happened by
// rethrowing the SAME exception.
7/27/2019 curs .NET 5.pdf
22/23
throw;
}
}
Exemplu (3) de definire a unei exceptii :
/** Created by SharpDevelop.
* User: info
* Date: 11/4/2004
* Time: 9:21 AM
*
* To change this template use Tools | Options | Coding | Edit Standard
Headers.
*/
using System;
using System.IO;
public class CustomException : Exception
{
object extraInfo;
public CustomException(string message, object extra) :base(message)
{
extraInfo = extra;
}
public override string ToString()
{
return "CustomException: " +
extraInfo.ToString() + "" +
base.Message + "" +
base.StackTrace;
}}
class CustomExceptionGenerator
{
static voidMain()
{
try
{
SomeMethod();
}
catch (CustomException ce)
{
Console.WriteLine(ce.ToString());
}
Console.ReadLine();
}
public static void SomeMethod()
{
//something went wrong
// Daca aici adaugam urmatorul cod:
7/27/2019 curs .NET 5.pdf
23/23
//
// int i, j,k ;
// i = 10 ;
// j = 0 ;
// k = i/j ;
//
// atunci apare Unhandled Exception
// si apoi exceptia creata.
//
throw new CustomException("Something went wrong", "ExtraInfo");
}
}
Iesirea este :
CustomException: ExtraInfo
Something went wrongat CustomExceptionGenerator.SomeMethod() in c:\Documents and Settings\info\My
Documents\SharpDevelop Projects\p5_exception1\Main.cs:line 49at CustomExceptionGenerator.Main() in c:\Documents and Settings\info\My Docum
ents\SharpDevelop Projects\p5_exception1\Main.cs:line 36
Ascunderea detaliilor de implementare
Exemplu (din exemple Microsft si reluat in foarte multe articole pe Internet) :
Acest exemplu arata cum ar trebui sa renuntam la validarea parametrilor metodelor si
folosirea exceptiilor in cadrul codului. Oricum decizia finala sta in mina programatorului.
public Int32 SomeMethod(Int32 x)
{try
{
return 100 / x;
}
catch (DivideByZeroException e)
{
throw new ArgumentOutOfRangeException("x", x,
"x cant be 0", e);
}
}
Exceptii netratate = echivalent cu lipsa blocului catch.