ধরো তোমার পিসি'র নোটপ্যাড-এ তুমি কিছু একটা সেভ করে রেখেছো । তোমায় সেটা কন্সল স্ক্রিনে দেখাতে চাচ্ছো , তাহলে কি করবে ?? চলো ছোট একটা প্রোগ্রাম দেখে আসি ।
ধরো , তুমি joy1 নামে একটা ফাইল সেইভ করে রেখেছো নোটপ্যাডে ।। এখন সেটাকে সরাসরি সেখান থেকে কন্সল স্ক্রিনে শো করাতে চাও তাহলে -----------------------
using System;
using System.IO;
public class Joy
{
public static void Main()
{
StreamReader streamreader = new StreamReader(@"C:\Users\Joy-PC\Documents\joy1.txt");
Console.WriteLine(streamreader.ReadToEnd());
streamreader.Close();
Console.ReadKey();
}
}
এখানে আমরা , using System.IO আগেই ব্যবহার করে নিয়েছি ।। কারণ , StreamReader ক্লাস'টি System.IO নামক নেইমস্পেইস এর অন্তর্ভুক্ত । তারপর , আমরা C:\Users\Joy-PC\Documents\joy1.txt এর মাধ্যমে সেই ফাইল এর ডিরেক্টরি লিখে ফেলি , StreamReader ক্লাস'টির কন্সট্রাক্টর এর মধ্যে ।। আর , শুধু ব্ল্যাকস্ল্যাস ( \ ) আমরা ডাবল কোটেশন এর ভেতরে ইউজ করতে পারবো না , এটা একটা এসকেপ সিকুয়েন্স ক্যারেক্টার । তাই , আগে @ ব্যবহারকরেছি ।। তারপর সেটা আমরা প্রিন্ট করেছি ।। আমরা এখানে , streamreader.Close() ব্যবহার এর মাধ্যমে , StreamReader ক্লাসের যে নতুন অবজেক্ট ক্রিয়েট করেছি তার সকল রিসোরস রিসোর্স মেমোরি থেকে ক্লিন করার জন্য ব্যবহার করেছি ।।
যাই হোক আমরা আজ যে বিষয়টি নিয়েই আলোচনা করবো সেটা হলো - Exception Handling | Exception হলো এক প্রকার Unforeseen Error যেটা আমাদের প্রোগ্রাম যখন এক্সিকিউট হয় , তখন ঘটে ।। ধরো , তুমিই তোমার joy1.txt ফাইলের নাম চেইঞ্জ করে অন্য একটা নাম দিলে ।। তারপর উপরের কোড রান করো ,তাহলে কি হবে ??
স্ক্রিনে তুমি , কিছু হিজিবিজি লিকা দেখতে পাবে । আসলে এগুলো হলো এরর , যার প্রথমেই তুমি দেখতে পাবে -- "Unhandled Exception:System.IO.FileNotFound Exception..."
তাই না ?? এখানেই কিন্তু তুমি দেখতে পাচ্ছো সেই Exception এর কথা । আমরা কিন্তু , এই "Unhandled Exception " কে handle করতে পারি ।। আজকে আমরা এগুলোই শিখবো ।।
আর তাছাড়াও এই Exception এর যেসব তথ্য আউটুপুট-এ দেখাচ্ছে , এসব আমরা যারা নতুন তারা কিছু না বুঝলেও , এসব কিন্তু খুবই মূল্যবান অনেক তথ্য বহন করে হ্যাকারদের জন্য ।। তাই আমাদের অবশ্যই জানতে হবে , Exception এর তথ্যগুলি কিভাবে ?? handle করতে পারি ।। চলো একটা কোড দেখে আসি --
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
StreamReader streamreader = new StreamReader(@"C:\Users\Joy-PC\Documents\joy.txt");
Console.WriteLine(streamreader.ReadToEnd());
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
Console.ReadKey();
}
}
আমাদের .NET ফ্রেমওয়ার্কের খাতিরে -- একটা Exception ক্লাস দেয়াই আছে যার বেশ কয়েকটি প্রোপার্টি আছে ।। যার ভেতরে Message & StackTrace প্রোপারটি মূলত আমাদের এক্সসেপশন সম্পরকে তথ্য ও ভূল প্রোগ্রামের কতো নাম্বার লাইনে আছে ?? সেটা বলে দিবে ।। এখন তুমি বুঝবে কি করে ? কতো নাম্বার লাইন কোনটা ?? প্রথম প্রথম বুঝতে সমস্যা হতেপারে , সেই জন্য তোমায়
Cntrl+G প্রেইস করলেই ।। একটা ফর্ম আসবে , সেখানে তুমি যতো নাম্বার লিখবে ? তোমায় ততো নাম্বার লাইনে মাউস এর দাগ চলে যাবে। দেখে নাও ... এখানে আমরা try ও catch ব্লক ইউজ করেছি । যদি কোনো এক্সসেপশন নাই থাকতো , তাহলে catch ব্লকের কোনো কিছু প্রিন্ট হবে না । কিন্তু , try ব্লকে কোনো এক্সসেপশন থাকলে সেটা catch ব্লকে প্রিন্ট করবে ।।
এখন একটা জিনিস আমাদের জেনে রাখতে হবে , উপরে যেটা ঘটছে , সেটা মূলত FileNotFound Exception । এটাও একটা ক্লাস ,যেটা Exception ক্লাস থেকে ইনহেরিটেড হয়েছে ।। চলো একটু দেখে আসি -----
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
StreamReader streamreader = new StreamReader(@"C:\Users\Joy-PC\Documents\joy.txt");
Console.WriteLine(streamreader.ReadToEnd());
}
catch(FileNotFoundException ex)
{
Console.WriteLine("{0} File May Doesn't Exist, Please Check\n\n\n", ex.FileName);
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
Console.ReadKey();
}
}
এখানে আমরা , FileNotFoundException ক্লাস ব্যবহার করেছি ।। যার একটা প্রোপার্টি আছে FileName নামে ।। যার সাহা্য্যে , আমরা ফাইলের নামটিও শো করাতে পারছি ,যে ফাইল থেকে আমরা রিড করতে চাচ্ছিলাম ।। প্রোগ্রামটি রান করিয়ে দেখে নাও , আর তারপর আমরা Message ও StackTrace প্রোপার্টির দ্বারা অনেক মেসেজ শো করাই ।। তুমি কি বুঝতে পারছো যে -- একটু একটু করে তুমি Exception Handling করা শুরু করেছো ।।
নীচের কোড দেখে আসি চলো -------------------------
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
StreamReader streamreader = new StreamReader(@"C:\UsersJoy-PC\Documents\joy.txt");
Console.WriteLine(streamreader.ReadToEnd());
}
catch(FileNotFoundException ex)
{
Console.WriteLine("{0} File May Doesn't Exist, Please Check\n\n\n", ex.FileName);
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
Console.ReadKey();
}
}
এখানে আমরা কিন্তু , ফাইলের ডিরেক্টরি ইচ্ছে করে আমি বদলে দিয়েছি ,খেয়াল করে দেখো ।। এখন আমি যদি রান করাই তাহলে কি হবে ??? আউটপুটে দেখবে ---DirectoryNotFoundException তাই না ?? এর মানে ?? এটা FileNotFoundException নয় ।। তাই তুমি , FileNotFoundException এর catch ব্লক দিয়ে DirectoryNotFoundException এক্সশেপশন কে হ্যান্ডল করতে পারবে না । তুমি উপরের কোড রান করে দেখো , তূমি যেটা শো করাতে চাইছিলে সেটা কিন্তু কনসল স্ক্রিনে দেখাচ্ছে না। একটু ভালো করে খেয়াল করে দেখো ।।
তাহলে DirectoryNotFoundException এর ক্ষেত্রে তুমি কি কি করবে ?? বুঝতেই পারছো , DirectoryNotFoundException ক্লাস অথবা সবার মাদার ক্লাস Exception ক্লাসও ব্যবহার করতে পারো ।। তবে , DirectoryNotFoundException ক্লাসের কিন্তু কোনো FileName প্রোপার্টি নেই , সেদিকে খেয়াল রেখো ।।
এখান থেকে কিন্তু আমরা বড়ো একটা ব্যপার এর বাস্তব রুপ শিখে গেছি , সেটা কি ?? ইনহেরিটেন্স এর কারণে , আমাদের বেইস ক্লাস Exception এর রেফারেন্স ভ্যারিয়েবল যেকোনো স্পেসিফিক ডেরাইভড Exception ক্লাস এর অব্জেক্ট কে পয়েন্ট করতে পারছে ।। এটা কিন্তু ইনহেরিটেন্স এর বড়ো একটা উদাহরণ ।।
আরো একটা বিষয় , মাথায় রাখা উচিত ।সেটা হলো , স্পেসিফিক ক্লাস যেমন FileNotFoundException ক্লাস কিন্তু এর বেইস ক্লাস Exception এর আগে বসবে ।। এটা মাথায় রাখতে হবে ।।
একটা বিষয় আরো ক্লিয়ার হওয়া উচিত , সেটা হলো আমরা যখন try ব্লকে streamreader.Close(); ইউজ করছি , সেটা কি কখনো কাজ করছে ?? নাকি করছে না ?? আসলে এই লাইন আসার
আগেই যদি কখনো Exception হয়ে যায় , তাহলে । তাহলে কিন্তু ঐ লাইন এক্সিকিউট হয় না । এর মানে ,হিপ মেমোরি থেকে এসব রিসোর্স গুলো ফ্রি হয় না ।। যেটা আমাদের অবশ্যই মাথায় রাখা উচিত ।।
তাহলে কি করবো এখোন ?? হুম ,একটা আরো ব্লক ইউজ করা যায় -যার নাম হলো finally ব্লক । যার ভেতরে আমরা streamreader.Close(); ইউজ করবো । কারণ , Exception থাকুক আর নাই থাকুক । আমাদের এই finally ব্লক এক্সিকিউট হবেই ।।
try
{
StreamReader streamreader = new StreamReader(@"C:\UsersJoy-PC\Documents\joy.txt");
Console.WriteLine(streamreader.ReadToEnd());
streamreader.Close();
}
চলো আমরা একবার একটা প্রোগ্রাম দেখে আসি , এটা নিয়ে ।।
using System;
using System.IO;
public class Joy
{
public static void Main()
{
StreamReader streamreader = null;
try
{
streamreader = new StreamReader(@"C:\UsersJoy-PC\Documents\joy.txt");
Console.WriteLine(streamreader.ReadToEnd());
streamreader.Close();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
Console.WriteLine("Finally block Executed!!");
Console.ReadKey();
streamreader.Close();
}
Console.ReadKey();
}
}
এটা Exception সহ ছিলো ।। এখন একটা Exception ছাড়া কোড লিখে দেখি ---- finally ব্লক এক্সিকিউট হয় কি না ?? চলো --------------
using System;
using System.IO;
public class Joy
{
public static void Main()
{
StreamReader streamreader = null;
try
{
streamreader = new StreamReader(@"C:\Users\Joy-PC\Documents\joy1.txt");
Console.WriteLine(streamreader.ReadToEnd());
streamreader.Close();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
Console.WriteLine("Finally block Executed!!");
Console.ReadKey();
streamreader.Close();
}
Console.ReadKey();
}
}
এবার Exception ছাড়াই দেখলাম , দুই ক্ষেত্রেই কিন্তু আমাদের finally ব্লক এক্সিকিউট হয়েছে । সো , আমরা এই ব্লক ইউজ করবো ।। আবার অনেক Exception এর ক্ষেত্রে যদি StreamReader ক্লাসের অবজেক্ট ফাইল থেকে রিড নাই করতে পারে ( মানে , Exception থাকে ) তাহলে , StreamReader ক্লাসের অব্জেক্ট নালই থেকে যায় ।। তাই , finally ব্লকের এক্সিকিউট হয় না । তাই আমরা জিনিসটাকে আরো একটু সুন্দরভাবে এইভাবে লিখতে পারি --
finally
{
if( streamreader!=null){
Console.WriteLine("Finally block Executed!!");
Console.ReadKey();
streamreader.Close();
}
}
আশা করি , বিষয়টা খুবই স্পষ্ট হয়েছে ।। এখানে আরো একটি প্রশ্ন মনের ভেতরে আসতেই পারে , আমাদের - সেটা হলো ,আমরা শুধু শুধু আরো একটা finally নামে একটা ব্লক খুলে কোডগুলো এক্সিকিউট করালাম কেনো ?? আমরা তো এই ব্লকের ভেতরের কোডগুলো এমনিতেই লিখতে পারতাম , এই ব্লক ছাড়া - তাতে কি অসুবিধা হত ??
প্রশ্নটি খুবই ভালো প্রশ্ন , কিন্তু - একটি কথা জেনে রাখা উচিত ।। যদি , আমাদের কোনো এক ধরণের Exception হয়েই থাকে এবং সেটার ফলে StreamReader ক্লাসের অব্জেক্ট নাল নাই থাকে । তাহলে ,ক্যাচ ব্লকে ঢোকার পরে এটা এর পরের আর কোনো কোড এক্সিকিউট করতে দিবে না , তাই আমরা সবসময় finally ব্লকই ইউজ করবো ,এটা খুবই ভালো একটা অভ্যাস ।।
আচ্ছা যাই হোক , এবার আমরা একটু বিরতি নিয়ে তারপর এরপরের আলোচনা শুরু করবো ।। তোমরা যারা আছো , তারা উপরের অংশটুকুই আগে ভালো করে বোঝার টড়াই করো , তারপর নিচের অংশটুকু বোঝা যাবে ।।
চলো এবার আমরা একটা সংখ্যাকে শূণ্য দ্বারা ভাগ দিয়ে দেখি , কি ধরনের Exception হয় ??? নীচে কোড দেখে আসি চলো ---
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
int a = Convert.ToInt32(Console.ReadLine());
int b = Convert.ToInt32(Console.ReadLine());
int result = a / b;
Console.WriteLine(result);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
}
}
এখন ধরো , এটা কোন ধরনের Exception ?? সেটা আমরা যে ফাইল থেকে এতদিন রিড করেছি , সেই ফাইলে রাইট করি ( লিখে ফেলি ) ।। দেখি চলো কোড ----------
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
int a = Convert.ToInt32(Console.ReadLine());
int b = Convert.ToInt32(Console.ReadLine());
int result = a / b;
Console.WriteLine(result);
}
catch(Exception ex)
{
string filepath = @"C:\Users\Joy-PC\Documents\joy1.txt";
StreamWriter sw=new StreamWriter (filepath);
sw.WriteLine(ex.GetType().Name);
sw.Close();
}
Console.ReadKey();
}
}
এখানে আমরা কোন ধরনের Exception ? সেটা জানার জন্য GetType() মেথোড এবং এর প্রোপার্টি Name ইউজ করছি ।। এখন উপরের কোড রান করে - তারপর ঠিকঠাক দুইটি আউটপুট এর প্রথমটি যেকোনো নাম্বার দাও আর , সেকেন্ড নাম্বারটি শূণ্য দাও । তাহলে তুমি , তারপরে তোমার যে ফাইলে সেইভ করছো - সেখানে গিয়ে দেখো । অটোমেটিক , তোমার ঐ ফাইলে এটা যে ধরনের Exception ( DivideByZeroException ) লিখা উঠে গেছে ।। এভাবে আমরা অনেক কিছুই ফাইলে লিখাতে পারবে , যেমন Message প্রপার্টি সহ অনেককিছুই | ।
আচ্ছা এবার আসো পুরোনো কথায় - আমি যে ফাইল ডিরেক্টরি লিখেছি , সেটা ভুল লিখতে চাই এর মানে ( FileNotFound Exception) ঘটাতে চাই চলো দেখি কি করা যায় ???
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
int a = Convert.ToInt32(Console.ReadLine());
int b = Convert.ToInt32(Console.ReadLine());
int result = a / b;
Console.WriteLine(result);
}
catch(Exception ex)
{
string filepath = @"C:\Users\Joy-PC\Documents\joy.txt";
if (File.Exists(filepath))
{
StreamWriter sw = new StreamWriter(filepath);
sw.WriteLine(ex.GetType().Name);
sw.Close();
}
else
{
throw new FileNotFoundException(filepath + "is not found", ex);
}
}
}
}
উপরের কোডটি রান করে দেখো । তাহলে কি দেখলে ??? আমাদের উদ্দেশ্য ছিলো DivideByZeroException , কিন্তু - আমরা নতুন একটা উটকো ঝামেলা FileNotFoundException । কিন্তু এই দুইটা Exception আনার পরে ।। আমরা কোনোটাই হ্যান্ডেল করতে পারছি না ।।
সেকেন্ডটার জন্য , প্রথম Exception টাও এখন ফাইলে রাইট করে পারছি না । তো চলো , এই সমস্যা থেকে কিভাবে ,উদ্ধার পাওয়া যায় ?? সেই চেষ্টা করি ।। আচ্ছা একটা জিনিস ক্লিয়ার হয়ে নেই যে - আমাদের একদম প্রথম Exception ছিলো DivideByZeroException , তাই না ?? আর তারপরের সেকেন্ড Exception টা হলো -- FileNotFoundException ।। প্রোগ্রামের ভাষায় আমরা প্রথম টাকে InnerException বলবো , আর পরেরটাকে Current Exception বলবো , ঠিক আছে ??? চলো এবার আসল কাজটা সেরে আসি --
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
try
{
int a = Convert.ToInt32(Console.ReadLine());
int b = Convert.ToInt32(Console.ReadLine());
int result = a / b;
Console.WriteLine(result);
}
catch (Exception ex)
{
string filepath = @"C:\Users\Joy-PC\Documents\joy.txt";
if (File.Exists(filepath))
{
StreamWriter sw = new StreamWriter(filepath);
sw.WriteLine(ex.GetType().Name);
sw.Close();
}
else
{
throw new FileNotFoundException(filepath + "is not found", ex);
}
}
}
catch(Exception es)
{
Console.WriteLine("Current Exception = {0}", es.GetType().Name);
Console.WriteLine("Inner Exception = {0}", es.InnerException.GetType().Name);
Console.ReadKey();
}
}
}
তাহলে এখানে আমরা আরো একটা try & catch ইউজ করলাম , কেনো ?? কারণ আমরা যদি প্রথমেই Exception পাই , তাহলে সেটাকে catch করার জন্য ভেতরে একটা catch ব্লক ইউজ করেছি , তাই না ?? কিন্তু যখন , সেই catch ব্লকেও Exception পাবো , তখন কি করবো , তাই আরো এই পুরোটাকেই একটা try ব্লকে ঢুকিয়ে দিয়েছি এবং তারপর আরো একটা catch ব্লক বাইরে ইউজ করেছি ।। আশা করি এইটুকু বুঝতে পেরেছো ।। এখন , নতুনত্ব বলতে আমরা ভেতরের ক্যাচ ব্লকের Exception এর জন্য , InnerException ইউজ করেছি , এইটুকুই । এখানে কিন্তু একটা কাহিনি আছে throw new FileNotFoundException(filepath + "is not found", ex); এর মাধ্যমে কিন্তু আসলে আমরা ওই প্রথম Exception এর রেফারেন্স ভ্যারিয়েবল ( অব্জেক্ট ) আমাদের নতুন বাইরের Exception ক্লাসে পাঠিয়ে দিয়েছি । যা InnerException তে পয়েন্ট করা আছে , এই কারণেই --- es.InnerException.GetType().Name লিখলে সেই ভেতরের Exception এর টাইপ পেয়ে যাচ্ছো । আশা করি , বিষয়টা ক্লিয়ার হয়েছে ।।
আচ্ছা একটা বিষয় পরিষ্কার করেই নেই , তুমি যদি শুধু আউটার Exception শো করাতে চাও , তাহলে কি করতে হবে ?? চলো দেখে আসি --
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
try
{
int a = Convert.ToInt32(Console.ReadLine());
int b = Convert.ToInt32(Console.ReadLine());
int result = a / b;
Console.WriteLine(result);
}
catch (Exception ex)
{
string filepath = @"C:\Users\Joy-PC\Documents\joy.txt";
if (File.Exists(filepath))
{
StreamWriter sw = new StreamWriter(filepath);
sw.WriteLine(ex.GetType().Name);
sw.Close();
}
else
{
throw new FileNotFoundException(filepath + "is not found");
}
}
}
catch(Exception es)
{
Console.WriteLine("Current Exception = {0}", es.GetType().Name);
if (es.InnerException != null)
{
Console.WriteLine("Inner Exception = {0}", es.InnerException.GetType().Name);
}
Console.ReadKey();
}
}
}
এখানে , যেহেতু আমরা শুধু একটা মাত্র মানে , সেকেন্ড'টা শো করাতে চাই । তাহলে ভেতরের কন্সট্রাক্টরে ওই ( অরিজিনাল / ইনার ) Exception এর রেফারেন্স ভ্যারিয়েবল পাস করাবো না । আর এইদিকে , যদি আমি প্যারামিটার কনস্ট্রাক্টরে পাস না করাই ।। তাহলে এদিকে আমাদের বাইরের Exception ক্লাসের গুরুত্বপূর্ণ একটা প্রোপার্টি InnerException টা নাল থাকবে , আর তাই আমি একটা if স্টেইটমেন্ট ইউজ করে , চেইক করে দেখালাম es.InnerException != null যদি খালি না হয় , তাহলেই শুধুমাত্র Console.WriteLine("Inner Exception = {0}", es.InnerException.GetType().Name); লাইন প্রিন্ট করবে অন্যথায় প্রিন্ট করবে না ।। আশা করি বিষয়গুলো আরো ক্লিয়ার হচ্ছে ।।
আচ্ছা এখন কিছুটা বিরতি নিয়ে আমরা এর পরের বিষয়গুলো আলোচনা করবো , এর পরের আলোচনা দেখার আগে ---- আগেরটুকু ভালো করে পড়ে ও বুঝে নেয়া উচিত ।।
আমরা , আমাদের Exception এর সময় যে যে মেসেজ শো করে সেটা এক এক Exception অনুযায়ী এক এক রকম , এখানে আমাদের কোনো হাত নেই , আমরা শুধু কখন কোনটা দেখাবে ?? শুধু এইটুকুই হ্যান্ডল করতে পারি ।। কিন্তু আমরা যদি কখনো নিজে নিজেই নতুন নতুন Exception ক্রিয়েট করে কাস্টমাইজ করতে পারতাম ! তাহলে ভালৈ হতো , চলো দেখে আসি ।।
এটা দেখার আগে , ইনহেরিটেন্স ও এক্সশেপশন নিয়ে বেসিক একদম ক্লিয়ার থাকতে হবে , না হলে এই বিষয়টা একদমই অন্যরকম লাগবে ।। চলো ......।।
প্রথমে আমরা একটা ক্লাস খুলে , সেটার বেইস ক্লাস হিসেবে Exception ক্লাস বসিয়ে দেবো , অন্যথায় আমরা আমাদের মতো করে কাজ করাতে পারবো না । তারপর , আমরা তিনটা কন্সট্রাক্টর ক্রিয়েট করবো ।। আগে আমরা , throw new Exception(); লিখে ভেতরে কিছু লিখলেই শো করাতো , কারণ এদের ডিফল্ট কন্সট্রাক্টর আছে , কিন্তু আমরা নতুন যে নতুন Exception ক্লাস বানিয়েছি , তাতে --
কোনো ডিফল্ট কন্সট্রাক্টর তো নেই তাই আমরা , আমাদের নতুন ক্লাসের বেইস ক্লাস এর কন্সট্রাক্টরকেই ইউজ করবো , তাহলে কষ্ট করে আর লিখতে হবে না ।
public class UserLoggedInException :Exception
{
public UserLoggedInException():base()
{
}
public UserLoggedInException(string Message):base(Message)
{
}
public UserLoggedInException(string Message,Exception innerException):base(Message,innerException)
{
}
}
আমরা শুধু কাস্টমাইজই নয় , আমাদের বানানো Exception ক্লাসের যদি কখনো innerException ট্র্যাক করানোরও প্রয়োজন পড়ে , তখন আমরা তিন নাম্বার কন্সট্রাক্টর দিয়ে শো করাতে পারবো ।।
আচ্ছা এখন একদমই নতুন একটা বিষয় নিয়ে জানবো , সেটা হলো ---------------- অ্যাপ্লিকেশন ডমেইন । আমাদের এই বানানো ক্লাসটি সাধারণত তখনই কাজ করবে ,যখন সেইম অ্যাপ্লিকেশন ডোমেইন থাকবে ।। এর মানে , ধরো - আমার দুইটা অ্যাপ্লিকেশন আছে একটার নাম A & আরো একটার নাম হলো B | এই অ্যাপ্লিকেশন দুইটি একে অপরের সাথে কথা বলতে চায় , তাহলে ?? কি করতে হবে ?? A অ্যাপ্লিকেশনের অবজেক্টগুলোকে B অ্যাপ্লিকেশনের যে বাউন্ডারি আছে , সেটা ক্রস করতে হবে । আর এই জন্য দুইটা অ্যাপ্লিকেশন এরই অব্জেক্টগুলোকে সিরিয়ালাইজেশন করতে হবে , তাহলে তুমি যদি তোমার অব্জেক্ট গুলোকে এক অ্যাপ্লিকেশন ডোমেইন থেকে অন্য অ্যাপ্লিকেশন ডোমেইন-এ মুভ করাএ চাও তাহলে একটা প্যাকেজ আকারে একটা থেকে আরেকটায় মুভ করতে পারে , এই জন্য অব্জেক্টগুলোকে সিরিয়ালাইজেশন করতে হবে । তাহলে চলো সিরিয়ালাইজেশন করে এর জন্য আরো একটা কন্সট্রাক্টর ক্রিয়েট করে ফেলি ----
using System;
using System.IO;
using System.Runtime.Serialization;
public class Joy
{
public static void Main()
{
throw new UserLoggedInException("User Is already Logged In , No Duplicate ");
}
[Serializable]
public class UserLoggedInException :Exception
{
public UserLoggedInException():base()
{
}
public UserLoggedInException(string Message):base(Message)
{
}
public UserLoggedInException(string Message,Exception innerException):base(Message,innerException)
{
}
public UserLoggedInException(SerializationInfo info,StreamingContext context ):base(info,context)
{
}
}
}
নতুনত্বের মধ্যে আমরা নতুন সিস্টেম ইঙ্কলুড করেছি ------খেয়াল করে দেখে নাও , আপাতত এই সিরিয়ালাইজেশন নিয়ে না ভাবলেও চলবে , বাট একটু বেসিক জেনে রাখা ভালো ।।
সব শেষে আমাদের আরো একটা বিষয় ক্লিয়ার হওয়া উচিত যে , এই Exception এর শুধু শুধু ব্যবহার যেনো না করি ।। যেমন আমরা ,নিচের মতো করে যেনো না করি ।
using System;
using System.IO;
using System.Runtime.Serialization;
public class Joy
{
public static void Main()
{
try
{
int a = Convert.ToInt32(Console.ReadLine());
}
catch(Exception ex)
{
Console.WriteLine("InputFormat Is Not Correct");
Console.ReadKey();
}
}
}
এরকমভাবে খুব শজেই আমরা লিখতে পারি , বাট এইসব ছোটখাট বিষয়ে Try.Parse মেথোড ইউজ করলেই পারি , তা সত্ত্বেও -- শুধু শুধু Exception ইউজ করা ঠিক হবে না ।। চলো , Try.Parse মেথোড দিয়ে করে আসি একবার -----------
using System;
using System.IO;
using System.Runtime.Serialization;
public class Joy
{
public static void Main()
{
int result = 0;
bool IsPossible = Int32.TryParse(Console.ReadLine(),out result);
if(IsPossible)
{
Console.WriteLine("Your Input Is {0}", result);
}
else
{
Console.WriteLine("Input Format Isn't Correct");
}
}
}
আশা করি বুঝতে পেরেছো , এসব ক্ষেত্রে আমরা শুধু শুধু Exception ইউজ করবো না ।। যাই হোক আজ এইটুকুই ---------------------------------------
ধরো , তুমি joy1 নামে একটা ফাইল সেইভ করে রেখেছো নোটপ্যাডে ।। এখন সেটাকে সরাসরি সেখান থেকে কন্সল স্ক্রিনে শো করাতে চাও তাহলে -----------------------
using System;
using System.IO;
public class Joy
{
public static void Main()
{
StreamReader streamreader = new StreamReader(@"C:\Users\Joy-PC\Documents\joy1.txt");
Console.WriteLine(streamreader.ReadToEnd());
streamreader.Close();
Console.ReadKey();
}
}
এখানে আমরা , using System.IO আগেই ব্যবহার করে নিয়েছি ।। কারণ , StreamReader ক্লাস'টি System.IO নামক নেইমস্পেইস এর অন্তর্ভুক্ত । তারপর , আমরা C:\Users\Joy-PC\Documents\joy1.txt এর মাধ্যমে সেই ফাইল এর ডিরেক্টরি লিখে ফেলি , StreamReader ক্লাস'টির কন্সট্রাক্টর এর মধ্যে ।। আর , শুধু ব্ল্যাকস্ল্যাস ( \ ) আমরা ডাবল কোটেশন এর ভেতরে ইউজ করতে পারবো না , এটা একটা এসকেপ সিকুয়েন্স ক্যারেক্টার । তাই , আগে @ ব্যবহারকরেছি ।। তারপর সেটা আমরা প্রিন্ট করেছি ।। আমরা এখানে , streamreader.Close() ব্যবহার এর মাধ্যমে , StreamReader ক্লাসের যে নতুন অবজেক্ট ক্রিয়েট করেছি তার সকল রিসোরস রিসোর্স মেমোরি থেকে ক্লিন করার জন্য ব্যবহার করেছি ।।
যাই হোক আমরা আজ যে বিষয়টি নিয়েই আলোচনা করবো সেটা হলো - Exception Handling | Exception হলো এক প্রকার Unforeseen Error যেটা আমাদের প্রোগ্রাম যখন এক্সিকিউট হয় , তখন ঘটে ।। ধরো , তুমিই তোমার joy1.txt ফাইলের নাম চেইঞ্জ করে অন্য একটা নাম দিলে ।। তারপর উপরের কোড রান করো ,তাহলে কি হবে ??
স্ক্রিনে তুমি , কিছু হিজিবিজি লিকা দেখতে পাবে । আসলে এগুলো হলো এরর , যার প্রথমেই তুমি দেখতে পাবে -- "Unhandled Exception:System.IO.FileNotFound Exception..."
তাই না ?? এখানেই কিন্তু তুমি দেখতে পাচ্ছো সেই Exception এর কথা । আমরা কিন্তু , এই "Unhandled Exception " কে handle করতে পারি ।। আজকে আমরা এগুলোই শিখবো ।।
আর তাছাড়াও এই Exception এর যেসব তথ্য আউটুপুট-এ দেখাচ্ছে , এসব আমরা যারা নতুন তারা কিছু না বুঝলেও , এসব কিন্তু খুবই মূল্যবান অনেক তথ্য বহন করে হ্যাকারদের জন্য ।। তাই আমাদের অবশ্যই জানতে হবে , Exception এর তথ্যগুলি কিভাবে ?? handle করতে পারি ।। চলো একটা কোড দেখে আসি --
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
StreamReader streamreader = new StreamReader(@"C:\Users\Joy-PC\Documents\joy.txt");
Console.WriteLine(streamreader.ReadToEnd());
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
Console.ReadKey();
}
}
আমাদের .NET ফ্রেমওয়ার্কের খাতিরে -- একটা Exception ক্লাস দেয়াই আছে যার বেশ কয়েকটি প্রোপার্টি আছে ।। যার ভেতরে Message & StackTrace প্রোপারটি মূলত আমাদের এক্সসেপশন সম্পরকে তথ্য ও ভূল প্রোগ্রামের কতো নাম্বার লাইনে আছে ?? সেটা বলে দিবে ।। এখন তুমি বুঝবে কি করে ? কতো নাম্বার লাইন কোনটা ?? প্রথম প্রথম বুঝতে সমস্যা হতেপারে , সেই জন্য তোমায়
Cntrl+G প্রেইস করলেই ।। একটা ফর্ম আসবে , সেখানে তুমি যতো নাম্বার লিখবে ? তোমায় ততো নাম্বার লাইনে মাউস এর দাগ চলে যাবে। দেখে নাও ... এখানে আমরা try ও catch ব্লক ইউজ করেছি । যদি কোনো এক্সসেপশন নাই থাকতো , তাহলে catch ব্লকের কোনো কিছু প্রিন্ট হবে না । কিন্তু , try ব্লকে কোনো এক্সসেপশন থাকলে সেটা catch ব্লকে প্রিন্ট করবে ।।
এখন একটা জিনিস আমাদের জেনে রাখতে হবে , উপরে যেটা ঘটছে , সেটা মূলত FileNotFound Exception । এটাও একটা ক্লাস ,যেটা Exception ক্লাস থেকে ইনহেরিটেড হয়েছে ।। চলো একটু দেখে আসি -----
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
StreamReader streamreader = new StreamReader(@"C:\Users\Joy-PC\Documents\joy.txt");
Console.WriteLine(streamreader.ReadToEnd());
}
catch(FileNotFoundException ex)
{
Console.WriteLine("{0} File May Doesn't Exist, Please Check\n\n\n", ex.FileName);
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
Console.ReadKey();
}
}
এখানে আমরা , FileNotFoundException ক্লাস ব্যবহার করেছি ।। যার একটা প্রোপার্টি আছে FileName নামে ।। যার সাহা্য্যে , আমরা ফাইলের নামটিও শো করাতে পারছি ,যে ফাইল থেকে আমরা রিড করতে চাচ্ছিলাম ।। প্রোগ্রামটি রান করিয়ে দেখে নাও , আর তারপর আমরা Message ও StackTrace প্রোপার্টির দ্বারা অনেক মেসেজ শো করাই ।। তুমি কি বুঝতে পারছো যে -- একটু একটু করে তুমি Exception Handling করা শুরু করেছো ।।
নীচের কোড দেখে আসি চলো -------------------------
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
StreamReader streamreader = new StreamReader(@"C:\UsersJoy-PC\Documents\joy.txt");
Console.WriteLine(streamreader.ReadToEnd());
}
catch(FileNotFoundException ex)
{
Console.WriteLine("{0} File May Doesn't Exist, Please Check\n\n\n", ex.FileName);
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
Console.ReadKey();
}
}
এখানে আমরা কিন্তু , ফাইলের ডিরেক্টরি ইচ্ছে করে আমি বদলে দিয়েছি ,খেয়াল করে দেখো ।। এখন আমি যদি রান করাই তাহলে কি হবে ??? আউটপুটে দেখবে ---DirectoryNotFoundException তাই না ?? এর মানে ?? এটা FileNotFoundException নয় ।। তাই তুমি , FileNotFoundException এর catch ব্লক দিয়ে DirectoryNotFoundException এক্সশেপশন কে হ্যান্ডল করতে পারবে না । তুমি উপরের কোড রান করে দেখো , তূমি যেটা শো করাতে চাইছিলে সেটা কিন্তু কনসল স্ক্রিনে দেখাচ্ছে না। একটু ভালো করে খেয়াল করে দেখো ।।
তাহলে DirectoryNotFoundException এর ক্ষেত্রে তুমি কি কি করবে ?? বুঝতেই পারছো , DirectoryNotFoundException ক্লাস অথবা সবার মাদার ক্লাস Exception ক্লাসও ব্যবহার করতে পারো ।। তবে , DirectoryNotFoundException ক্লাসের কিন্তু কোনো FileName প্রোপার্টি নেই , সেদিকে খেয়াল রেখো ।।
এখান থেকে কিন্তু আমরা বড়ো একটা ব্যপার এর বাস্তব রুপ শিখে গেছি , সেটা কি ?? ইনহেরিটেন্স এর কারণে , আমাদের বেইস ক্লাস Exception এর রেফারেন্স ভ্যারিয়েবল যেকোনো স্পেসিফিক ডেরাইভড Exception ক্লাস এর অব্জেক্ট কে পয়েন্ট করতে পারছে ।। এটা কিন্তু ইনহেরিটেন্স এর বড়ো একটা উদাহরণ ।।
আরো একটা বিষয় , মাথায় রাখা উচিত ।সেটা হলো , স্পেসিফিক ক্লাস যেমন FileNotFoundException ক্লাস কিন্তু এর বেইস ক্লাস Exception এর আগে বসবে ।। এটা মাথায় রাখতে হবে ।।
একটা বিষয় আরো ক্লিয়ার হওয়া উচিত , সেটা হলো আমরা যখন try ব্লকে streamreader.Close(); ইউজ করছি , সেটা কি কখনো কাজ করছে ?? নাকি করছে না ?? আসলে এই লাইন আসার
আগেই যদি কখনো Exception হয়ে যায় , তাহলে । তাহলে কিন্তু ঐ লাইন এক্সিকিউট হয় না । এর মানে ,হিপ মেমোরি থেকে এসব রিসোর্স গুলো ফ্রি হয় না ।। যেটা আমাদের অবশ্যই মাথায় রাখা উচিত ।।
তাহলে কি করবো এখোন ?? হুম ,একটা আরো ব্লক ইউজ করা যায় -যার নাম হলো finally ব্লক । যার ভেতরে আমরা streamreader.Close(); ইউজ করবো । কারণ , Exception থাকুক আর নাই থাকুক । আমাদের এই finally ব্লক এক্সিকিউট হবেই ।।
try
{
StreamReader streamreader = new StreamReader(@"C:\UsersJoy-PC\Documents\joy.txt");
Console.WriteLine(streamreader.ReadToEnd());
streamreader.Close();
}
চলো আমরা একবার একটা প্রোগ্রাম দেখে আসি , এটা নিয়ে ।।
using System;
using System.IO;
public class Joy
{
public static void Main()
{
StreamReader streamreader = null;
try
{
streamreader = new StreamReader(@"C:\UsersJoy-PC\Documents\joy.txt");
Console.WriteLine(streamreader.ReadToEnd());
streamreader.Close();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
Console.WriteLine("Finally block Executed!!");
Console.ReadKey();
streamreader.Close();
}
Console.ReadKey();
}
}
এটা Exception সহ ছিলো ।। এখন একটা Exception ছাড়া কোড লিখে দেখি ---- finally ব্লক এক্সিকিউট হয় কি না ?? চলো --------------
using System;
using System.IO;
public class Joy
{
public static void Main()
{
StreamReader streamreader = null;
try
{
streamreader = new StreamReader(@"C:\Users\Joy-PC\Documents\joy1.txt");
Console.WriteLine(streamreader.ReadToEnd());
streamreader.Close();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
Console.WriteLine("Finally block Executed!!");
Console.ReadKey();
streamreader.Close();
}
Console.ReadKey();
}
}
এবার Exception ছাড়াই দেখলাম , দুই ক্ষেত্রেই কিন্তু আমাদের finally ব্লক এক্সিকিউট হয়েছে । সো , আমরা এই ব্লক ইউজ করবো ।। আবার অনেক Exception এর ক্ষেত্রে যদি StreamReader ক্লাসের অবজেক্ট ফাইল থেকে রিড নাই করতে পারে ( মানে , Exception থাকে ) তাহলে , StreamReader ক্লাসের অব্জেক্ট নালই থেকে যায় ।। তাই , finally ব্লকের এক্সিকিউট হয় না । তাই আমরা জিনিসটাকে আরো একটু সুন্দরভাবে এইভাবে লিখতে পারি --
finally
{
if( streamreader!=null){
Console.WriteLine("Finally block Executed!!");
Console.ReadKey();
streamreader.Close();
}
}
আশা করি , বিষয়টা খুবই স্পষ্ট হয়েছে ।। এখানে আরো একটি প্রশ্ন মনের ভেতরে আসতেই পারে , আমাদের - সেটা হলো ,আমরা শুধু শুধু আরো একটা finally নামে একটা ব্লক খুলে কোডগুলো এক্সিকিউট করালাম কেনো ?? আমরা তো এই ব্লকের ভেতরের কোডগুলো এমনিতেই লিখতে পারতাম , এই ব্লক ছাড়া - তাতে কি অসুবিধা হত ??
প্রশ্নটি খুবই ভালো প্রশ্ন , কিন্তু - একটি কথা জেনে রাখা উচিত ।। যদি , আমাদের কোনো এক ধরণের Exception হয়েই থাকে এবং সেটার ফলে StreamReader ক্লাসের অব্জেক্ট নাল নাই থাকে । তাহলে ,ক্যাচ ব্লকে ঢোকার পরে এটা এর পরের আর কোনো কোড এক্সিকিউট করতে দিবে না , তাই আমরা সবসময় finally ব্লকই ইউজ করবো ,এটা খুবই ভালো একটা অভ্যাস ।।
আচ্ছা যাই হোক , এবার আমরা একটু বিরতি নিয়ে তারপর এরপরের আলোচনা শুরু করবো ।। তোমরা যারা আছো , তারা উপরের অংশটুকুই আগে ভালো করে বোঝার টড়াই করো , তারপর নিচের অংশটুকু বোঝা যাবে ।।
চলো এবার আমরা একটা সংখ্যাকে শূণ্য দ্বারা ভাগ দিয়ে দেখি , কি ধরনের Exception হয় ??? নীচে কোড দেখে আসি চলো ---
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
int a = Convert.ToInt32(Console.ReadLine());
int b = Convert.ToInt32(Console.ReadLine());
int result = a / b;
Console.WriteLine(result);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
}
}
এখন ধরো , এটা কোন ধরনের Exception ?? সেটা আমরা যে ফাইল থেকে এতদিন রিড করেছি , সেই ফাইলে রাইট করি ( লিখে ফেলি ) ।। দেখি চলো কোড ----------
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
int a = Convert.ToInt32(Console.ReadLine());
int b = Convert.ToInt32(Console.ReadLine());
int result = a / b;
Console.WriteLine(result);
}
catch(Exception ex)
{
string filepath = @"C:\Users\Joy-PC\Documents\joy1.txt";
StreamWriter sw=new StreamWriter (filepath);
sw.WriteLine(ex.GetType().Name);
sw.Close();
}
Console.ReadKey();
}
}
এখানে আমরা কোন ধরনের Exception ? সেটা জানার জন্য GetType() মেথোড এবং এর প্রোপার্টি Name ইউজ করছি ।। এখন উপরের কোড রান করে - তারপর ঠিকঠাক দুইটি আউটপুট এর প্রথমটি যেকোনো নাম্বার দাও আর , সেকেন্ড নাম্বারটি শূণ্য দাও । তাহলে তুমি , তারপরে তোমার যে ফাইলে সেইভ করছো - সেখানে গিয়ে দেখো । অটোমেটিক , তোমার ঐ ফাইলে এটা যে ধরনের Exception ( DivideByZeroException ) লিখা উঠে গেছে ।। এভাবে আমরা অনেক কিছুই ফাইলে লিখাতে পারবে , যেমন Message প্রপার্টি সহ অনেককিছুই | ।
আচ্ছা এবার আসো পুরোনো কথায় - আমি যে ফাইল ডিরেক্টরি লিখেছি , সেটা ভুল লিখতে চাই এর মানে ( FileNotFound Exception) ঘটাতে চাই চলো দেখি কি করা যায় ???
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
int a = Convert.ToInt32(Console.ReadLine());
int b = Convert.ToInt32(Console.ReadLine());
int result = a / b;
Console.WriteLine(result);
}
catch(Exception ex)
{
string filepath = @"C:\Users\Joy-PC\Documents\joy.txt";
if (File.Exists(filepath))
{
StreamWriter sw = new StreamWriter(filepath);
sw.WriteLine(ex.GetType().Name);
sw.Close();
}
else
{
throw new FileNotFoundException(filepath + "is not found", ex);
}
}
}
}
উপরের কোডটি রান করে দেখো । তাহলে কি দেখলে ??? আমাদের উদ্দেশ্য ছিলো DivideByZeroException , কিন্তু - আমরা নতুন একটা উটকো ঝামেলা FileNotFoundException । কিন্তু এই দুইটা Exception আনার পরে ।। আমরা কোনোটাই হ্যান্ডেল করতে পারছি না ।।
সেকেন্ডটার জন্য , প্রথম Exception টাও এখন ফাইলে রাইট করে পারছি না । তো চলো , এই সমস্যা থেকে কিভাবে ,উদ্ধার পাওয়া যায় ?? সেই চেষ্টা করি ।। আচ্ছা একটা জিনিস ক্লিয়ার হয়ে নেই যে - আমাদের একদম প্রথম Exception ছিলো DivideByZeroException , তাই না ?? আর তারপরের সেকেন্ড Exception টা হলো -- FileNotFoundException ।। প্রোগ্রামের ভাষায় আমরা প্রথম টাকে InnerException বলবো , আর পরেরটাকে Current Exception বলবো , ঠিক আছে ??? চলো এবার আসল কাজটা সেরে আসি --
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
try
{
int a = Convert.ToInt32(Console.ReadLine());
int b = Convert.ToInt32(Console.ReadLine());
int result = a / b;
Console.WriteLine(result);
}
catch (Exception ex)
{
string filepath = @"C:\Users\Joy-PC\Documents\joy.txt";
if (File.Exists(filepath))
{
StreamWriter sw = new StreamWriter(filepath);
sw.WriteLine(ex.GetType().Name);
sw.Close();
}
else
{
throw new FileNotFoundException(filepath + "is not found", ex);
}
}
}
catch(Exception es)
{
Console.WriteLine("Current Exception = {0}", es.GetType().Name);
Console.WriteLine("Inner Exception = {0}", es.InnerException.GetType().Name);
Console.ReadKey();
}
}
}
তাহলে এখানে আমরা আরো একটা try & catch ইউজ করলাম , কেনো ?? কারণ আমরা যদি প্রথমেই Exception পাই , তাহলে সেটাকে catch করার জন্য ভেতরে একটা catch ব্লক ইউজ করেছি , তাই না ?? কিন্তু যখন , সেই catch ব্লকেও Exception পাবো , তখন কি করবো , তাই আরো এই পুরোটাকেই একটা try ব্লকে ঢুকিয়ে দিয়েছি এবং তারপর আরো একটা catch ব্লক বাইরে ইউজ করেছি ।। আশা করি এইটুকু বুঝতে পেরেছো ।। এখন , নতুনত্ব বলতে আমরা ভেতরের ক্যাচ ব্লকের Exception এর জন্য , InnerException ইউজ করেছি , এইটুকুই । এখানে কিন্তু একটা কাহিনি আছে throw new FileNotFoundException(filepath + "is not found", ex); এর মাধ্যমে কিন্তু আসলে আমরা ওই প্রথম Exception এর রেফারেন্স ভ্যারিয়েবল ( অব্জেক্ট ) আমাদের নতুন বাইরের Exception ক্লাসে পাঠিয়ে দিয়েছি । যা InnerException তে পয়েন্ট করা আছে , এই কারণেই --- es.InnerException.GetType().Name লিখলে সেই ভেতরের Exception এর টাইপ পেয়ে যাচ্ছো । আশা করি , বিষয়টা ক্লিয়ার হয়েছে ।।
আচ্ছা একটা বিষয় পরিষ্কার করেই নেই , তুমি যদি শুধু আউটার Exception শো করাতে চাও , তাহলে কি করতে হবে ?? চলো দেখে আসি --
using System;
using System.IO;
public class Joy
{
public static void Main()
{
try
{
try
{
int a = Convert.ToInt32(Console.ReadLine());
int b = Convert.ToInt32(Console.ReadLine());
int result = a / b;
Console.WriteLine(result);
}
catch (Exception ex)
{
string filepath = @"C:\Users\Joy-PC\Documents\joy.txt";
if (File.Exists(filepath))
{
StreamWriter sw = new StreamWriter(filepath);
sw.WriteLine(ex.GetType().Name);
sw.Close();
}
else
{
throw new FileNotFoundException(filepath + "is not found");
}
}
}
catch(Exception es)
{
Console.WriteLine("Current Exception = {0}", es.GetType().Name);
if (es.InnerException != null)
{
Console.WriteLine("Inner Exception = {0}", es.InnerException.GetType().Name);
}
Console.ReadKey();
}
}
}
এখানে , যেহেতু আমরা শুধু একটা মাত্র মানে , সেকেন্ড'টা শো করাতে চাই । তাহলে ভেতরের কন্সট্রাক্টরে ওই ( অরিজিনাল / ইনার ) Exception এর রেফারেন্স ভ্যারিয়েবল পাস করাবো না । আর এইদিকে , যদি আমি প্যারামিটার কনস্ট্রাক্টরে পাস না করাই ।। তাহলে এদিকে আমাদের বাইরের Exception ক্লাসের গুরুত্বপূর্ণ একটা প্রোপার্টি InnerException টা নাল থাকবে , আর তাই আমি একটা if স্টেইটমেন্ট ইউজ করে , চেইক করে দেখালাম es.InnerException != null যদি খালি না হয় , তাহলেই শুধুমাত্র Console.WriteLine("Inner Exception = {0}", es.InnerException.GetType().Name); লাইন প্রিন্ট করবে অন্যথায় প্রিন্ট করবে না ।। আশা করি বিষয়গুলো আরো ক্লিয়ার হচ্ছে ।।
আচ্ছা এখন কিছুটা বিরতি নিয়ে আমরা এর পরের বিষয়গুলো আলোচনা করবো , এর পরের আলোচনা দেখার আগে ---- আগেরটুকু ভালো করে পড়ে ও বুঝে নেয়া উচিত ।।
আমরা , আমাদের Exception এর সময় যে যে মেসেজ শো করে সেটা এক এক Exception অনুযায়ী এক এক রকম , এখানে আমাদের কোনো হাত নেই , আমরা শুধু কখন কোনটা দেখাবে ?? শুধু এইটুকুই হ্যান্ডল করতে পারি ।। কিন্তু আমরা যদি কখনো নিজে নিজেই নতুন নতুন Exception ক্রিয়েট করে কাস্টমাইজ করতে পারতাম ! তাহলে ভালৈ হতো , চলো দেখে আসি ।।
এটা দেখার আগে , ইনহেরিটেন্স ও এক্সশেপশন নিয়ে বেসিক একদম ক্লিয়ার থাকতে হবে , না হলে এই বিষয়টা একদমই অন্যরকম লাগবে ।। চলো ......।।
প্রথমে আমরা একটা ক্লাস খুলে , সেটার বেইস ক্লাস হিসেবে Exception ক্লাস বসিয়ে দেবো , অন্যথায় আমরা আমাদের মতো করে কাজ করাতে পারবো না । তারপর , আমরা তিনটা কন্সট্রাক্টর ক্রিয়েট করবো ।। আগে আমরা , throw new Exception(); লিখে ভেতরে কিছু লিখলেই শো করাতো , কারণ এদের ডিফল্ট কন্সট্রাক্টর আছে , কিন্তু আমরা নতুন যে নতুন Exception ক্লাস বানিয়েছি , তাতে --
কোনো ডিফল্ট কন্সট্রাক্টর তো নেই তাই আমরা , আমাদের নতুন ক্লাসের বেইস ক্লাস এর কন্সট্রাক্টরকেই ইউজ করবো , তাহলে কষ্ট করে আর লিখতে হবে না ।
public class UserLoggedInException :Exception
{
public UserLoggedInException():base()
{
}
public UserLoggedInException(string Message):base(Message)
{
}
public UserLoggedInException(string Message,Exception innerException):base(Message,innerException)
{
}
}
আমরা শুধু কাস্টমাইজই নয় , আমাদের বানানো Exception ক্লাসের যদি কখনো innerException ট্র্যাক করানোরও প্রয়োজন পড়ে , তখন আমরা তিন নাম্বার কন্সট্রাক্টর দিয়ে শো করাতে পারবো ।।
আচ্ছা এখন একদমই নতুন একটা বিষয় নিয়ে জানবো , সেটা হলো ---------------- অ্যাপ্লিকেশন ডমেইন । আমাদের এই বানানো ক্লাসটি সাধারণত তখনই কাজ করবে ,যখন সেইম অ্যাপ্লিকেশন ডোমেইন থাকবে ।। এর মানে , ধরো - আমার দুইটা অ্যাপ্লিকেশন আছে একটার নাম A & আরো একটার নাম হলো B | এই অ্যাপ্লিকেশন দুইটি একে অপরের সাথে কথা বলতে চায় , তাহলে ?? কি করতে হবে ?? A অ্যাপ্লিকেশনের অবজেক্টগুলোকে B অ্যাপ্লিকেশনের যে বাউন্ডারি আছে , সেটা ক্রস করতে হবে । আর এই জন্য দুইটা অ্যাপ্লিকেশন এরই অব্জেক্টগুলোকে সিরিয়ালাইজেশন করতে হবে , তাহলে তুমি যদি তোমার অব্জেক্ট গুলোকে এক অ্যাপ্লিকেশন ডোমেইন থেকে অন্য অ্যাপ্লিকেশন ডোমেইন-এ মুভ করাএ চাও তাহলে একটা প্যাকেজ আকারে একটা থেকে আরেকটায় মুভ করতে পারে , এই জন্য অব্জেক্টগুলোকে সিরিয়ালাইজেশন করতে হবে । তাহলে চলো সিরিয়ালাইজেশন করে এর জন্য আরো একটা কন্সট্রাক্টর ক্রিয়েট করে ফেলি ----
using System;
using System.IO;
using System.Runtime.Serialization;
public class Joy
{
public static void Main()
{
throw new UserLoggedInException("User Is already Logged In , No Duplicate ");
}
[Serializable]
public class UserLoggedInException :Exception
{
public UserLoggedInException():base()
{
}
public UserLoggedInException(string Message):base(Message)
{
}
public UserLoggedInException(string Message,Exception innerException):base(Message,innerException)
{
}
public UserLoggedInException(SerializationInfo info,StreamingContext context ):base(info,context)
{
}
}
}
নতুনত্বের মধ্যে আমরা নতুন সিস্টেম ইঙ্কলুড করেছি ------খেয়াল করে দেখে নাও , আপাতত এই সিরিয়ালাইজেশন নিয়ে না ভাবলেও চলবে , বাট একটু বেসিক জেনে রাখা ভালো ।।
সব শেষে আমাদের আরো একটা বিষয় ক্লিয়ার হওয়া উচিত যে , এই Exception এর শুধু শুধু ব্যবহার যেনো না করি ।। যেমন আমরা ,নিচের মতো করে যেনো না করি ।
using System;
using System.IO;
using System.Runtime.Serialization;
public class Joy
{
public static void Main()
{
try
{
int a = Convert.ToInt32(Console.ReadLine());
}
catch(Exception ex)
{
Console.WriteLine("InputFormat Is Not Correct");
Console.ReadKey();
}
}
}
এরকমভাবে খুব শজেই আমরা লিখতে পারি , বাট এইসব ছোটখাট বিষয়ে Try.Parse মেথোড ইউজ করলেই পারি , তা সত্ত্বেও -- শুধু শুধু Exception ইউজ করা ঠিক হবে না ।। চলো , Try.Parse মেথোড দিয়ে করে আসি একবার -----------
using System;
using System.IO;
using System.Runtime.Serialization;
public class Joy
{
public static void Main()
{
int result = 0;
bool IsPossible = Int32.TryParse(Console.ReadLine(),out result);
if(IsPossible)
{
Console.WriteLine("Your Input Is {0}", result);
}
else
{
Console.WriteLine("Input Format Isn't Correct");
}
}
}
আশা করি বুঝতে পেরেছো , এসব ক্ষেত্রে আমরা শুধু শুধু Exception ইউজ করবো না ।। যাই হোক আজ এইটুকুই ---------------------------------------
No comments:
Post a Comment