0% found this document useful (0 votes)
24 views50 pages

Unit 3 Dot Net Exception

Uploaded by

richmakercasio
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
24 views50 pages

Unit 3 Dot Net Exception

Uploaded by

richmakercasio
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 50

Unit 3 - Exception & object life time and

Interface and Collections


The Basics of Object Lifetime
• Object lifetime is the time when a block of memory is
allocated to this object during some process of
execution and that block of memory is released when
the process ends.
• Once the object is allocated with memory, it is
necessary to release that memory so that it is used for
further processing, otherwise, it would result in
memory leaks. We have a class in .Net that releases
memory automatically for us when the object is no
longer used.
• A block of memory is allocated when
the new keyword is used to instantiate the new object
and the constructor is called.
• This block of memory is big enough to hold the
object. When we declare a class variable it is
allocated on the stack and the time it hits a new
keyword and then it is allocated on the heap.
• In other words, when an object of a class is created it
is allocated on the heap with the C# new keyword
operator. However, a new keyword returns a
reference to the object on the heap, not the actual
object itself. This reference variable is stored on the
stack for further use in applications.
• When the new operator is used to create an object,
memory is taken from the managed heap for this
object and the managed heap is more than just a
random chunk of memory accessed by the CLR.
• When the object is no longer used then it is de-
allocated from the memory so that this memory can
be reused.
• The key pillar of the .NET Framework is the
automatic garbage collection that manages memory
for all .NET applications. When an object is
instantiated the garbage collector will destroy the
object when it is no longer needed.
• There is no explicit memory deallocation since the
garbage collector monitors unused objects and does a
collection to free up memory that is an automatic process.
The Garbage Collector removes objects from the heap
when they are unreachable by any part of your codebase.

public static void MakeACar()


{
// If myCar is the only reference to the Car object,
// it may be destroyed when the method returns.
Car myCar = new Car();
...
}
• Notice that the Car reference (myCar) has been
created directly within the MakeACar()method and
has not been passed outside of the defining scope (via
a return value or ref/out parameters).
• Thus, once this method call completes, the myCar
reference is no longer reachable, and the associated
Car object is now a candidate for garbage collection.
• Understand, however, that you cannot guarantee that
this object will be reclaimed from memory
immediately after MakeACar() has completed.
• All you can assume at this point is that when the CLR
performs the next garbage collection, the myCar
object could be safely destroyed.
The Role of Application Roots
• Garbage collector determines when an object is “no longer needed”, but
To understand the details, you need to be aware of the notion of
application roots, where a root is a storage location containing a
reference to an object on the heap, a root can fall into any of the
following categories:
• References to global objects (while not allowed in C#,
CIL code does permit allocation of global objects)
• References to currently used static objects/static fields
• References to local objects within a given method
• References to object parameters passed into a method
• References to objects waiting to be finalized.
• Any CPU register that references a local object
• During a garbage collection process, the runtime will
investigate objects on the managed heap to determine if they
are still reachable (rooted) by the application. To do so, the
CLR(Common language runtime) will build an object graph,
which represents each reachable object on the heap.
• Object graphs are used to document all reachable objects & be
aware that the garbage collector will never graph the same
object twice.
• Assume the managed heap contains a set of objects named A,
B, C, D, E, F, and G. During a garbage collection, these
objects (as well as any internal object references they may
contain) are examined for active roots.
• Once the graph has been constructed, unreachable objects (which
we will assume are objects C and F) are marked as garbage.
• Figure 5-3 diagrams - a possible object graph for the scenario just
described (you can read the directional arrows using the phrase
depends on or requires, for example,“E depends on G and indirectly
B,” “A depends on nothing,” and so on)

Figure 5-3. Object graphs are constructed to determine which objects are
reachable by application roots.
.
• Once an object has been marked for termination (C and F in this
case—as they are not accounted for in the object graph), they are
swept (REMOVED) from memory.
• At this point, the remaining space on the heap is compacted,
which in turn will cause the CLR to modify the set of active
application roots to refer to the correct memory location (this is
done automatically and transparently).
Understanding Object Generations
• When the CLR is attempting to locate unreachable objects, it does
not literally examine each and every object placed on the managed
heap, doing so would involve considerable time, especially in larger
(i.e., real-world) applications.
• To help optimize the process, each object on the heap is assigned to
a specific “generation.” The idea behind generations is simple: The
longer an object has existed on the heap, the more likely it is to stay
there. For example, the object implementing Main() will be in
memory until the program terminates.
• objects that have been recently placed on the heap are likely to be
unreachable rather quickly (such as an object created within a
method scope). Given these assumptions, each object on the heap
belongs to one of the following generations:
• Generation 0: Identifies a newly allocated object that has
never been marked for collection
• Generation 1: Identifies an object that has survived a
garbage collection (i.e., it was marked for collection, but
was not removed due to the fact that the sufficient heap
space was acquired)
• Generation 2: Identifies an object that has survived more
than one sweep of the garbage Collector.
The garbage collector will investigate all generation 0
objects first. If marking and sweeping these objects results
in the required amount of free memory, any surviving
objects are promoted to generation.
The System.GC Type
• The base class libraries provide a class type named System.GC
that allows you to programmatically interact with the garbage
collector using a set of static members. The only time you will
make use of the members of System.GC is when you are
creating types that make use of unmanaged resources.
• Table 5-1. Select Members of the System.GC Type

System.GC Member Meaning in Life

AddMemoryPressure(), Allow you to specify a numerical value that represents the


calling
RemoveMemoryPressure() object’s “urgency level” regarding the garbage collection
process and thus never remove more pressure than the total
amount you have added.
Collect() Forces the GC to perform a garbage collection
System.GC Member Meaning in Life

GetGeneration() Returns the generation to which an object currently belongs.


GetTotalMemory() Returns the estimated amount of memory (in bytes) currently
allocated on the managed heap. The Boolean parameter
specifies whether the call should wait for garbage collection
to occur before returning.
MaxGeneration() Returns the maximum of generations supported on the target
system. Under Microsoft’s .NET 2.0, there are three possible
generations (0, 1, and 2).
SuppressFinalize() Sets a flag indicating that the specified object should not
have it¸ Finalize() method called.
WaitForPendingFinali Suspends the current thread until all finalizable objects have
zers() been finalized. This method is typically called directly after
invoking
GC.Collect(). Ponder the following Main() method, which illustrates select
members of System.GC:
CollectionCount() Returns a numerical value representing how many times a
given generation has been swept.
static void Main(string[] args)
{
// Print out estimated number of bytes on heap.
Console.WriteLine("Estimated bytes on heap: {0}",
GC.GetTotalMemory(false));

// MaxGeneration is zero based, so add 1 for display purposes.


Console.WriteLine("This OS has {0} object generations.\n",
(GC.MaxGeneration + 1));
Car refToMyCar = new Car("Zippy", 100);
Console.WriteLine(refToMyCar.ToString());

// Print out generation of refToMyCar object.


Console.WriteLine("Generation of refToMyCar is: {0}",
GC.GetGeneration(refToMyCar));
Console.ReadLine();
}
Meaning of Errors, Bugs and Exceptions
• Mistakes are bound to happen during programming. Problems
may occur due to bad code like overflow of array index,
invalid input etc. So, the programmer needs to handle all
possible types of problems. There are three terminologies to
define mistakes that may occur.
Bugs:
• Errors done by the programmer
• Example: making use of NULL pointer, referring array index
out of bound, not deleting allocated memory etc
Errors:
• Caused by user of the application
• For example: entering un-expected value in a textbox, say
USN
Exceptions:
• Runtime anomalies those are difficult to prevent
• Example: trying to open a corrupted file, trying to connect
non-existing database etc

The Role of .NET Exception Handling


• An exception is defined as an event that occurs during the
execution of a program that is unexpected by the program
code. The actions to be performed in case of occurrence of an
exception is not known to the program.
• In such a case, we create an exception object and call the
exception handler code. The execution of an exception handler
so that the program code does not crash is called exception
handling.
• Exception handling is important because it gracefully handles
an unwanted event, an exception so that the program code still
Keyword Definition

Used to define a try block. This block holds


try
the code that may throw an exception.

Used to define a catch block. This block


catch catches the exception thrown by the try
block.

Used to define the finally block. This block


finally
holds the default code.

throw Used to throw an exception manually.


// C# program to show how
// Exceptions occur in a program
using System;

class GFG {

static void Main(string[] args)


{
// Declare an array of max index 4
int[] arr = { 1, 2, 3, 4, 5 };

// Display values of array elements


for (int i = 0; i < arr.Length; i++) {
Console.WriteLine(arr[i]);
}

// Try to access invalid index of array


Console.WriteLine(arr[7]);
// An exception is thrown upon executing
// the above line
}
}
Runtime Error:
Unhandled Exception:
System.IndexOutOfRangeException: Index was outside the bounds of the
array.
at GFG.Main (System.String[] args) [0x0002e] in
<9fa39b3b4dec49eb8af89dc70d5a0618>:0
[ERROR] FATAL UNHANDLED EXCEPTION:
System.IndexOutOfRangeException: Index was outside the bounds of the
array.
at GFG.Main (System.String[] args) [0x0002e] in
<9fa39b3b4dec49eb8af89dc70d5a0618>:0

In the code given above, the array named ‘arr’ is defined for 5 elements,
indices 0 to 4. When we try to access the 7th element of the array, that is non-
existent, program code throws an exception and the above message is
displayed. The exception can be handled using the System.Exception class of
C#. This will be depicted in the code given below.
Exception Handling Using try-catch block
• The code given below shows how we can handle exceptions using the try-
catch block. The code that may generate an exception is placed inside the
try block.
• In this case, the access to the 7th element is put inside the try block. When
that statement is executed an exception is generated, which is caught by the
catch block. The object of the type IndexOutOfRangeException is used to
display a message to the user about the exception that has occurred.

Syntax:
try {
// statements that may cause an exception
}
catch( Exception obj) {
// handler code
}
using System;
class Program : System.Exception {
static void Main(string[] args)
{
int[] arr = { 1, 2, 3, 4, 5 };
for (int i = 0; i < arr.Length; i++) {
Console.WriteLine(arr[i]);
try {
// Try to access invalid index of array
Console.WriteLine(arr[7]);
// An exception is thrown upon executing the above line }
catch (IndexOutOfRangeException e) {
// The Message property of the object
// of type IndexOutOfRangeException
// is used to display the type of exception
// that has occurred to the user.
Console.WriteLine("An Exception has occurred : {0}", e.Message);
}
}
}
Output
1
2
3
4
5
An Exception has occurred : Index was outside the bounds of the array.

The System.Exception Base Class


• All user- and system-defined exceptions ultimately derive
from the System.Exception base class (which in turn derives
from System.Object). Core Members of the System.Exception
Type are shown below:
System.Exception Meaning
Property

HelpLink This property returns a URL to a help file describing the


error in full detail.
InnerException Used to obtain information about the previous exceptions
that caused the current exception to occur. The previous
exceptions are recorded by passing them into the constructor
of the most current exception. This is a read-only property.

Message Returns the textual description of a given error. The error


message itself is set as a constructor parameter. This is a
read-only property.

Source Returns the name of the assembly that threw the exception.
StackTrace Contains a string that identifies the sequence of calls that
triggered the exception. This is a read-only property.
TargetSite Returns a Method-Base type, which describes numerous
details about the method that threw the exception (ToString()
will identify the method by name). This is a read-only
property.
Throwing a Generic Exception
During the program, if any exception occurs, we can throw it to
either a specific exception like FileNotFoundException,
ArrayIndexOutOfBoundException, DivideByZeroException etc.
or we can through a generic exception directly using Exception
class. The object of Exception class can handle any type of
exception, as it is a base class for all type of exceptions.
using System;
class Test {
int Max=100;
public void Fun(int d) {
if(d>Max)
throw new Exception("crossed limit!!!");
else
Console.WriteLine("d={0}", d); }
public static void Main()
{
Test ob=new Test();
Console.WriteLine("Enter a number:");
int d=int.Parse(Console.ReadLine());
ob.Fun(d);
}
}
Output:
Enter a number: 12
d=12
Enter a number: 567
Unhandled Exception: System.Exception: crossed limit!!!
at Test.Fun(Int32 d)
at Test.Main()
In the above example, if the entered value d is greater than 100, then we are
throwing an exception. We are passing message “crossed limit” to a Message
property of Exception class.
Deciding exactly what constitutes throwing an exception and when to throw an
exception is up to the programmer.
Catching Exceptions
When a block of code is bound to throw an exception, it needs to be caught
using catch statement. Once we catch an exception, we can invoke the
members of System. Exception class. Using these members in the catch block,
we may display a message about the exception, store the information about the
error in a file, send a mail to administrator etc. For example,
using System;
class Test
{
int Max=100;
public void Fun(int d)
{
try
{
if(d>Max)
throw new Exception("crossed limit!!!");
}
catch(Exception e)
{
Console.WriteLine("{0}", e.Message);
}

Console.WriteLine("d={0}", d);
}
public static void Main()
{
Test ob=new Test();
Console.WriteLine("Enter a number:");
int d=int.Parse(Console.ReadLine());
ob.Fun(d);
}
}
Output:
Enter a number: 12
d=12
Enter a number: 123
crossed limit!!!
d=123
• In the above example, we are throwing an exception if d>100
and is caught. Throwing an exception using the statement –

throw new Exception (“Crossed Limit”);


means, creating an object of Exception class and passing that
object to catch block. While passing an object, we are passing the
message also, which will be an input for the Message property of
Exception class.
• A try block is a section of code used to check for any
exception that may be encountered during its scope. If an
exception is detected, the program control is sent to the
appropriate catch block. If the code within try block does not
trigger any exception, then the catch block is skipped fully and
program will continue to execute further.
The TargetSite Property:
• The System.Exception.TargetSite property allows to
determine various details about the method that threw
a given exception.
• Printing the value of TargetSite will display the return
type, name, and parameters of the method that threw
the exception.
• However, TargetSite does not simply return a string,
but a strongly typed System.Reflection.MethodBase
object.
• This type can be used to gather numerous details
regarding the offending method as well as the class
that defines the offending method.
The StackTrace Property:
• The System.Exception.StackTrace property allows
you to identify the series of calls that resulted in the
exception.
• Be aware that you never set the value of StackTrace
as it is established automatically at the time the
exception is created.
• The string returned from StackTrace documents the
sequence of calls that resulted in the throwing of this
exception.
using System;
class Test {
int Max=100;
public void Fun(int d) {
try {
if(d>Max)
throw new Exception(string.Format("crossed limit!!!")); }
catch(Exception e)
{
Console.WriteLine("{0}",e.Message); // crossed limit!!!
Console.WriteLine("{0}", e.TargetSite); //Void Fun(Int32)
Console.WriteLine("{0}",e.TargetSite.DeclaringType); //Test
Console.WriteLine("{0}", e.TargetSite.MemberType); //Method
Console.WriteLine("Stack:{0}", e.StackTrace);//at Test.Fun(Int32 d)
}
Console.WriteLine("d={0}", d);
}
public static void Main()
{
Test ob=new Test();
Console.WriteLine("Enter a number:");
int d=int.Parse(Console.ReadLine()); //assume d is 123
ob.Fun(d); }
}
NOTE: The comment lines for the statements within the function
Fun() are the outputs for the input d greater than 100.
The Helplink Property:
• The HelpLink property can be set to point the user to a
specific URL or standard Windows help file that contains
more detailed information.
• By default, the value managed by the HelpLink property is an
empty string.
• If you wish to fill this property with an interesting value, you
will need to do so before throwing the System.Exception type.
using System;
class Test
{
int Max=100;
public void Fun(int d)
{
try
{
if(d>Max)
{
Exception ex= new Exception("crossed limit!!!");
ex.HelpLink="g:\\Help.doc";
throw ex;
}
}
catch(Exception e)
{
Console.WriteLine("{0}", e.HelpLink); // G:\Help.doc
}
Console.WriteLine("d={0}", d);
}
public static void Main()
{
Test ob=new Test();
Console.WriteLine("Enter a number:");
int d=int.Parse(Console.ReadLine()); //say d=345
ob.Fun(d);
}
}
Using Multiple try-catch blocks
• In the code given below, we attempt to generate an exception
in the try block and catch it in one of the multiple catch
blocks.
• Multiple catch blocks are used when we are not sure about the
exception type that may be generated, so we write different
blocks to tackle any type of exception that is encountered.
• The finally block is the part of the code that has to be executed
irrespective of if the exception was generated or not. In the
program given below the elements of the array are displayed
in the finally block.
Syntax:
try {
// statements that may cause an exception
}
catch(Specific_Exception_type obj) {
// handler code
}
catch(Specific_Exception_type obj) {
// handler code
}...
finally {
//default code
}
using System;
class Program {
static void Main(string[] args)
{
int[] arr = {19, 0, 75, 52};

try {

// Try to generate an exception


for (int i = 0; i < arr.Length; i++) {
Console.WriteLine(arr[i] / arr[i + 1]);
}
}

// Catch block for invalid array access


catch (IndexOutOfRangeException e) {

Console.WriteLine("An Exception has occurred : {0}", e.Message);


}
// Catch block for attempt to divide by zero
catch (DivideByZeroException e) {

Console.WriteLine("An Exception has occurred : {0}", e.Message);


}
// Catch block for value being out of range
catch (ArgumentOutOfRangeException e) {
Console.WriteLine("An Exception has occurred : {0}", e.Message);
}
// Finally block
// Will execute irrespective of the above catch blocks
finally {
for (int i = 0; i < arr.Length; i++) {
Console.Write(" {0}", arr[i]);
}
}
}
}
Output:
An Exception has occurred : Attempted to divide by zero.
19 0 75 52
User Defined Exceptions
• User-defined exceptions are useful when we want to code
an exception that may not be defined by the language.
• For example, in a boiler room, if the temperature rises
above some threshold then the heat must be turned off.
• For understanding how user-defined exceptions are used
we take an example of a division by zero. Here we define
a class DivByZero that inherits from Exception and is
called by the DivisionOperation function when the
denominator is equal to zero.
• Since the call for the function is may or may not throw
an exception it is placed in the try block. A catch block is
defined to catch any exception of type Exception and the
Message property prints the type of exception that has
occurred.
// C# program to show the user defined exceptions
using System;
// User defined Exception class
// Child of Exception
class DivByZero : Exception {

// Constructor
public DivByZero()
{
Console.Write("Exception has occurred : ");
}
}
class Program {

// Method to perform Division


public double DivisionOperation(double numerator, double denominator)
{
// throw exception when denominator
// value is 0
if (denominator == 0)
throw new DivByZero();

// Otherwise return the result of the division


return numerator / denominator;
}
// Main
static void Main(string[] args)
{
Program obj = new Program();
double num = 9, den = 0, quotient;
try {
// Code block that may cause an exception
quotient = obj.DivisionOperation(num, den);
Console.WriteLine("Quotient = {0}", quotient);
}
// Catch block to catch the generic exception
catch (Exception e) {
// Message property of exception object e
// will give the specific type of the exception
Console.Write(e.Message); }
}
}
Output:
Exception has occurred : Exception of type 'DivByZero' was thrown.
Handling Multiple Exceptions
• We have seen a situation where a try block will have
corresponding catch block. But in reality, we may face a
situation where the code within try block may trigger
multiple possible exceptions. For example,
public void SpeedUp(int delta)
{
try
{
if(delta<0)
throw new ArgumentOutOfRangeException(“Ford Ikon”);
speed=current_speed + delta;
if(speed>max_speed)
throw new CarIsDeadException(“Ford Ikon”);
}
catch(CarIsDeadException e)
{
Console.WriteLine(“Method:{0}”, e.TargetSite);
Console.WriteLine(“Message:{0}”, e. Message);
}
catch(ArgumentOutOfRangeException e)
{
Console.WriteLine(“Method:{0}”, e.TargetSite);
Console.WriteLine(“Message:{0}”, e. Message); }
}
In the above example, if delta is less than zero, then
ArgumentOutOfRangeException is triggered. If the speed exceeds
MaxSpeed, then CarIsDeadException is thrown. While
constructing multiple catch blocks for a single try block, we must
be aware that it will be processed by the nearest available catch
block.
For example, the following code snippet generates compile-time error!!
try
{
----------
}
catch(Exception e)
{
--------------
}
catch(CarIsDeadException e)
{
--------------
}
catch(ArgumentOutOfRangeException e)
{
--------------
}
Here, the class Exception is a base class for all user-defined and built-in exceptions.
Hence, it can handle any type of exceptions. Thus, if Exception is the first catch-
block, the control will jump to that block itself and the other two exceptions are
unreachable
• Thus, during multiple exceptions, we have to design very
structured format. The very first catch block should contain
very specific exception or the most derived type in inheritance
hierarchy. Whereas the last catch block should be the most
general or the top most base class in inheritance hierarchy.
Generic Catch Statements:
• C# supports a generic catch block that does not explicitly
define the type of exception. That is, we can write –
catch
{
Console.WriteLine(“Some error has occurred”);
}
• But, using this type of catch blocks indicates that the
programmer is un-aware of the type of exception that is going
to occur, which is not acceptable. Hence it is always advised to
use specific type of exceptions.
Re-throwing Exceptions:
It is possible to re-throw an error to the previous caller.
For example–
try
{----------------
}
catch(CarIsDeadException e)
{
//handle CarIsDeadException partially or do something
throw e;
}
• In the above code, the statement throw e will throw
the exception again to CarIsDeadException.
The finally Block
• The try/catch block may be added with an optional Finally
block. The finally block contains a code that always executes
irrespective of any number of exceptions that may interfere
with the normal flow of execution.
• For example, we may want to turn-off radio within a car
before stopping the car due to any reason. Programmatically
speaking, before exiting from Main() function, we may need
to turn-off radio of a car. Then we can write –
public static void Main()
{
try
{
//increase speed
}
catch(CarIsDeadException e)
{
-----------
}
catch(ArgumentOutOfRangeException e)
{
--------------
}
Finally
{
CarName.TurnOffRadio();
}
}

You might also like