ইউজার-ডিফাইন্ড এক্সেপশন হলো আপনার কোডে ডিফাইন করা এমন যেকোনো ক্লাস, যা System.Exception থেকে ডিরাইভ করা। এটি ক্লাস ইনহেরিটেন্সের সব নিয়মই মেনে চলে, তবে তার সঙ্গে যোগ হয় আরও একটি ব্যাপার: কম্পাইলার ও ভাষার রানটাইম এসব ক্লাসের সঙ্গে বিশেষভাবে আচরণ করে, ফলে স্বাভাবিক কন্ট্রোল ফ্লোরের বাইরেও এদের ইনস্ট্যান্স থ্রো ও ক্যাচ করা যায়, যেমনটি exceptions অনুশীলনীতে আলোচনা করা হয়েছে। রানটাইম ও Microsoft Base Class Library-এর এক্সেপশন যেমন সব দিক থেকেই ব্যবহার করা যায়, ইউজার-ডিফাইন্ড এক্সেপশনও তেমনই।
এই বিশেষ আচরণ কেবল Exception থেকে ডিরাইভ করা ক্লাসের ক্ষেত্রেই খাটে। অন্য কোনো টাইপের ইনস্ট্যান্স আপনি থ্রো করতে পারবেন না।
ইউজার-ডিফাইন্ড এক্সেপশন প্রায়ই বাড়তি তথ্য বহন করতে ব্যবহার করা হয়, যেমন একটি মেসেজ ও অন্যান্য প্রাসঙ্গিক ডেটা, যাতে সেগুলো ক্যাচ করার রুটিনগুলোর হাতে পৌঁছে দেওয়া যায়। এরপর সেগুলো লগে রেকর্ড করা যায়, ব্যবহারকারীকে জানানো যায়, কিংবা রিট্রাই করার সময় কাজে লাগানো যায়। মেসেজ ও "inner" এক্সেপশন ধরে রাখার জন্য System.Exception-এ সুবিধাজনক ডেটা মেম্বার আর উপযুক্ত কনস্ট্রাক্টর আছে।
প্রথা অনুযায়ী এক্সেপশন ক্লাসের নাম "Exception" দিয়ে শেষ হয়, যেমন MyTerribleException।
থার্ড-পার্টি এক্সেপশন র্যাপ করা ও সমৃদ্ধ করার জন্য ইউজার-ডিফাইন্ড এক্সেপশন ব্যবহার করা একটি বহুল-দেখা প্যাটার্ন হলেও, সাধারণ পরামর্শ হলো এই ব্যবহারের বাইরে নিজের কোডে সেগুলো খুব উদারভাবে ব্যবহার করবেন না। এটিকে অ্যান্টি-প্যাটার্ন ধরা হয়। এই মতের বিরোধিতা আছে, আর বিতর্কের দুই পক্ষের মতই এই Stack Exchange পোস্টে দেখতে পাবেন।
এই আর্টিকেলটি ইউজার-ডিফাইন্ড এক্সেপশন সম্পর্কে ভালো একটি ভূমিকা।
এক্সেপশন তৈরি ও থ্রো করা নিয়ে তাদের নির্দেশনার অংশ হিসেবে .NET টিম সুপারিশ করে যে ইউজার-ডিফাইন্ড এক্সেপশনে বেশ কিছু সুবিধাজনক কনস্ট্রাক্টর থাকা উচিত। বেশিরভাগ ক্ষেত্রেই নিচে দেখানো সমন্বয়টিই যথাযথ।
public class IncompleteExerciseException : System.Exception
{
public IncompleteExerciseException() : base() { }
public IncompleteExerciseException(string message) : base(message) { }
public IncompleteExerciseException(string message, System.Exception inner) : base(message, inner) { }
}