নিক্ষেপ এবং নিক্ষেপ এর মধ্যে পার্থক্য


164

পার্থক্য কি

try { ... }
catch{ throw } 

এবং

try{ ... }
catch(Exception e) {throw new Exception(e.message) } 

দ্বিতীয়টি কোনও বার্তা দেখায় না কেন?


51
দ্বিতীয় স্নিপেটটি আমি দেখেছি এমন কোডগুলির মধ্যে সবচেয়ে খারাপ (তবে নিরীহ) লাইনগুলির মধ্যে একটি।
এসএলএক্স

উত্তর:


259

throw; মূল ব্যতিক্রমটি পুনর্বিবেচনা করে এবং এর মূল স্ট্যাক ট্রেস সংরক্ষণ করে।

throw ex;আসল ব্যতিক্রম ছোঁড়ে তবে স্ট্যাক ট্রেস পুনরায় সেট করে, আপনার catchব্লক অবধি সমস্ত স্ট্যাক ট্রেস তথ্য ধ্বংস করে ।


কখনও লেখেন নাthrow ex;


throw new Exception(ex.Message);আরও খারাপ। এটি একেবারে নতুন Exceptionউদাহরণ তৈরি করে , ব্যতিক্রমের মূল স্ট্যাক ট্রেস, পাশাপাশি এটির হারাতে। (যেমন, IOException)।
এছাড়াও, কিছু ব্যতিক্রম অতিরিক্ত তথ্য ধারণ করে (যেমন, ArgumentException.ParamName)।
throw new Exception(ex.Message); এই তথ্যও ধ্বংস করবে।

কিছু নির্দিষ্ট ক্ষেত্রে, আপনি সমস্ত ব্যতিক্রমগুলি একটি কাস্টম ব্যতিক্রম আইটেজে আবদ্ধ করতে চাইতে পারেন, যাতে ব্যতিক্রম ছোঁড়ার সময় কোডটি কী করছিল সে সম্পর্কে অতিরিক্ত তথ্য সরবরাহ করতে পারেন।

এটি করার জন্য, উত্তরাধিকার সূত্রে প্রাপ্ত একটি নতুন শ্রেণীর সংজ্ঞা দিন Exception, চারটি ব্যতিক্রমী নির্মাণকারীর সংযোজন করুন এবং বিকল্প InnerExceptionহিসাবে অতিরিক্ত তথ্য গ্রহণকারী অতিরিক্ত কন্সট্রাক্টর যুক্ত করুন এবং প্যারামিটার হিসাবে পাস করেexInnerException আপনার নতুন ব্যতিক্রম শ্রেণি নিক্ষেপ করুন । আসলটি পাস করে InnerExceptionআপনি স্ট্যাক ট্রেস সহ সমস্ত মূল ব্যতিক্রমের সমস্ত সম্পত্তি সংরক্ষণ করেন।


24
"নতুন ব্যতিক্রম ছোঁড়া (প্রাক্তন) আরও খারাপ।": আমি এই বিষয়ে একমত নই। কখনও কখনও আপনি একটি ব্যতিক্রমের ধরণটি পরিবর্তন করতে চান এবং তারপরে মূল ব্যতিক্রমটিকে অভ্যন্তরীণ ব্যতিক্রম হিসাবে রাখাই আপনার পক্ষে সবচেয়ে ভাল। যদিও এটি throw new MyCustomException(myMessage, ex);অবশ্যই হওয়া উচিত ।
ডার্ক ভোলমার

9
@ 0xA3: আমি বোঝাতে চেয়েছি ex.Message, এটি আরও খারাপ।
স্ল্যাक्स

6
মানক নির্মাতারা বাস্তবায়নের পাশাপাশি কাস্টম ব্যতিক্রমও করা উচিত [Serializable()]
ডার্ক ভোলমার

21
হ্যাঁ, আমরা আপনাকে ব্যতিক্রম পছন্দ করি যাতে আমরা আপনার ব্যাতিক্রমকে ব্যতিক্রম করি যাতে আপনি যখন ধরেন তখন আপনি ধরতে পারেন।
দার্ট কন্টিনেন্ট

2
@ এসএলক্স: যখন আপনি throw;আসল লাইন নম্বর যেখানে ব্যতিক্রম ঘটেছিল তার লাইন নম্বর দ্বারা প্রতিস্থাপন করা হবে throw;। আপনি কীভাবে এটি পরিচালনা করার পরামর্শ দিচ্ছেন? stackoverflow.com/questions/2493779/…
এরিক জে

34

প্রথমটি মূল স্ট্যাকট্রেস সংরক্ষণ করে:

try { ... }
catch
{
    // Do something.
    throw;
}

দ্বিতীয়টি আপনাকে ব্যতিক্রম এবং / অথবা বার্তা এবং অন্যান্য ডেটার ধরণের পরিবর্তন করতে দেয়:

try { ... } catch (Exception e)
{
    throw new BarException("Something broke!");
}

তৃতীয় উপায় আছে যেখানে আপনি অভ্যন্তরীণ ব্যতিক্রমটি পাস করেন:

try { ... }
catch (FooException e) {
    throw new BarException("foo", e);
} 

আমি ব্যবহার করার পরামর্শ দিচ্ছি:

  • প্রথমটি যদি আপনি ত্রুটি সম্পর্কিত কোনও তথ্য পরিষ্কার না করতে চান বা ত্রুটি সম্পর্কিত তথ্য না যোগ করেন।
  • তৃতীয়টি যদি আপনি ত্রুটি সম্পর্কে আরও তথ্য যুক্ত করতে চান।
  • দ্বিতীয়টি যদি আপনি তথ্য আড়াল করতে চান (অবিশ্বস্ত ব্যবহারকারীদের থেকে)।

6

অন্য একটি বিষয় যে আমি কাউকে বানাতে দেখিনি:

যদি আপনি আপনার ক্যাচ}} ব্লকে কিছু না করেন, চেষ্টা করে দেখুন ... ধরা অর্থহীন। আমি সব সময় এটি দেখতে:

try 
{
  //Code here
}
catch
{
    throw;
}

বা তার থেকেও খারাপ:

try 
{
  //Code here
}
catch(Exception ex)
{
    throw ex;
}

সবচেয়ে খারাপ:

try 
{
  //Code here
}
catch(Exception ex)
{
    throw new System.Exception(ex.Message);
}

আমি একমত, আপনার যদি শেষ অবধি না থাকে।
টনি রসম্যান

1
@ToniRossmann এই ক্ষেত্রে আমি চেষ্টা না করেই চেষ্টা করব..ফেলা পর্যন্ত যদি আপনি ফেলে দেওয়া ব্যতীত অন্য কিছু না করেন;
জেএলওয়ার্লো

4

throwস্ট্যাকের ট্রেস ধরে রেখে ধরা পড়া ব্যতিক্রমটিকে আবার ছুঁড়ে ফেলা হয়, তবে ধরা পড়া ব্যতিক্রমের throw new Exceptionকিছু বিবরণ হারিয়ে ফেলে।

আপনি সাধারণত throwসেই সময়ে সম্পূর্ণরূপে পরিচালনা না করে ব্যতিক্রম লগ করতে নিজেই ব্যবহার করবেন ।

ব্ল্যাকওয়াস্পের সি # তে থ্রোয়িং ব্যতিক্রম শিরোনামের একটি ভাল নিবন্ধ রয়েছে ।


4

একটি নতুন ব্যতিক্রম ছোঁড়া বর্তমান স্ট্যাকের ট্রেসকে দূরে সরিয়ে দেয়।

throw;মূল স্ট্যাক ট্রেস ধরে রাখতে হবে এবং প্রায় সবসময় আরও দরকারী। এই নিয়মের ব্যতিক্রম হ'ল আপনি যখন নিজের নিজস্ব একটি কাস্টম ব্যতিক্রম ব্যতিক্রমটি মোড়তে চান। তারপরে আপনার করা উচিত:

catch(Exception e)
{
    throw new CustomException(customMessage, e);
}

3

throwএকটি ধরা ব্যতিক্রম পুনর্বিবেচনার জন্য হয়। কল চেইনটি পাস করার আগে আপনি যদি ব্যতিক্রম কিছু করতে চান তবে এটি কার্যকর হতে পারে।

throwকোনও যুক্তি ছাড়াই ব্যবহার ডিবাগিং উদ্দেশ্যে কল স্ট্যাক সংরক্ষণ করে।


0

আপনি যদি চান তবে আপনি একটি নতুন ব্যতিক্রম ছোঁড়াতে পারেন, মূল সেটটি অভ্যন্তরীণ ব্যতিক্রম হিসাবে।


0

আপনার দ্বিতীয় উদাহরণটি ব্যতিক্রমের স্ট্যাক ট্রেসটিকে পুনরায় সেট করবে। প্রথমটি সবচেয়ে সঠিকভাবে ব্যতিক্রমের উত্স সংরক্ষণ করে। এছাড়াও আপনি আসল প্রকারটি আনপ্রেপ করেছেন যা আসলে কী ভুল হয়েছে তা জানার মূল কী ... যদি কার্যকারিতার জন্য দ্বিতীয়টি প্রয়োজন হয় - উদাহরণস্বরূপ প্রসারিত তথ্য যুক্ত করতে বা বিশেষ ধরণের যেমন একটি কাস্টম 'হ্যান্ডলেবল এক্সেক্সশন' এর সাথে পুনরায় মোড়ানোর জন্য ঠিক তখনই থাকুন নিশ্চিত যে ইনারএক্সেপশন সম্পত্তিটিও সেট করা আছে!


হ্যাঁ, এটি সেই প্রশ্নগুলির মধ্যে একটি যেখানে আপনাকে দ্রুত লিখতে হবে। ;)
রবার্ট হার্ভে

0

সর্বাধিক গুরুত্বপূর্ণ পার্থক্য হ'ল দ্বিতীয় প্রকাশটি ব্যতিক্রমের ধরণগুলি মুছে দেয়। এবং ব্যতিক্রম ধরণের ব্যতিক্রমগুলি ধরতে গুরুত্বপূর্ণ ভূমিকা পালন করে:

public void MyMethod ()
{
    // both can throw IOException
    try { foo(); } catch { throw; }
    try { bar(); } catch(E) {throw new Exception(E.message); }
}

(...)

try {
    MyMethod ();
} catch (IOException ex) {
    Console.WriteLine ("Error with I/O"); // [1]
} catch (Exception ex) {
    Console.WriteLine ("Other error");    // [2]
}

যদি foo()ছুড়ে ফেলে IOException, [1]ক্যাচ ব্লক ব্যতিক্রম ধরবে। কিন্তু যখন bar()ছুড়ে ফেলা হয় IOException, তখন এটি সরল Exceptionপিঁপড়ে রূপান্তরিত হবে [1]ক্যাচ ব্লক দ্বারা ধরা পড়বে না ।


0

নিক্ষেপ বা নিক্ষিপ্ত, উভয়ই ব্যতিক্রম ছোঁড়া বা পুনর্বিবেচনা করতে ব্যবহৃত হয়, যখন আপনি কেবল ত্রুটি সম্পর্কিত তথ্য লগইন করেন এবং কলারের কাছে কোনও তথ্য ফেরত পাঠাতে চান না, আপনি কেবল ত্রুটিটিকে ধরা এবং ছেড়ে দেওয়ার জন্য লগইন করতে চান। তবে যদি আপনি কল বা থ্রো প্রাক্তন ব্যবহারকারী কলারের ব্যতিক্রম সম্পর্কে কিছু অর্থপূর্ণ তথ্য প্রেরণ করতে চান তবে inc এখন থ্রো এবং থ্রো প্রাক্তনের মধ্যে পার্থক্য হ'ল থ্রো স্ট্যাক ট্রেস এবং অন্যান্য তথ্য সংরক্ষণ করে তবে থ্রো প্রাক্তন একটি নতুন ব্যতিক্রম বস্তু তৈরি করে এবং তাই মূল স্ট্যাক ট্রেস হারিয়ে যায়। সুতরাং কখন আমাদের থ্রোক এবং থ্রো ই ব্যবহার করা উচিত, এখনও কয়েকটি পরিস্থিতি রয়েছে যাতে আপনি কল স্ট্যাকের তথ্য পুনরায় সেট করতে চাইলে একটি ব্যতিক্রম পুনর্বিবেচন করতে চান। উদাহরণস্বরূপ, যদি পদ্ধতিটি কোনও লাইব্রেরিতে থাকে এবং আপনি কলিং কোড থেকে লাইব্রেরির বিশদটি গোপন করতে চান, আপনি প্রয়োজনীয়ভাবে কল স্ট্যাকটি লাইব্রেরির মধ্যে ব্যক্তিগত পদ্ধতি সম্পর্কে তথ্য অন্তর্ভুক্ত করতে চান না। সেক্ষেত্রে আপনি গ্রন্থাগারের পাবলিক পদ্ধতিতে ব্যতিক্রমগুলি ধরতে পারেন এবং তারপরে এগুলি পুনরায় উত্সাহিত করতে পারেন যাতে সেই সর্বজনীন পদ্ধতিতে কল স্ট্যাক শুরু হয়।


0

নিক্ষেপ; আসল ব্যতিক্রমটি পুনরায় করুন এবং ব্যতিক্রমের প্রকারটি রাখুন।

নতুন ব্যতিক্রম নিক্ষেপ (); মূল ব্যাতিক্রমের পুনরায় সরান এবং ব্যতিক্রম স্ট্যাক ট্রেস পুনরায় সেট করুন

প্রাক্তন নিক্ষেপ; ব্যতিক্রম স্ট্যাক ট্রেস পুনরায় সেট করুন এবং ব্যতিক্রম প্রকারটি পুনরায় সেট করুন


-1

এখানে উত্তরগুলির মধ্যে কোনওটিই তফাতটি দেখায় না, যা পার্থক্যটি বোঝার জন্য সংগ্রামকারীদের পক্ষে সহায়ক হতে পারে। এই নমুনা কোডটি বিবেচনা করুন:

using System;
using System.Collections.Generic;

namespace ExceptionDemo
{
   class Program
   {
      static void Main(string[] args)
      {
         void fail()
         {
            (null as string).Trim();
         }

         void bareThrow()
         {
            try
            {
               fail();
            }
            catch (Exception e)
            {
               throw;
            }
         }

         void rethrow()
         {
            try
            {
               fail();
            }
            catch (Exception e)
            {
               throw e;
            }
         }

         void innerThrow()
         {
            try
            {
               fail();
            }
            catch (Exception e)
            {
               throw new Exception("outer", e);
            }
         }

         var cases = new Dictionary<string, Action>()
         {
            { "Bare Throw:", bareThrow },
            { "Rethrow", rethrow },
            { "Inner Throw", innerThrow }
         };

         foreach (var c in cases)
         {
            Console.WriteLine(c.Key);
            Console.WriteLine(new string('-', 40));
            try
            {
               c.Value();
            } catch (Exception e)
            {
               Console.WriteLine(e.ToString());
            }
         }
      }
   }
}

যা নিম্নলিখিত আউটপুট উত্পন্ন করে:

Bare Throw:
----------------------------------------
System.NullReferenceException: Object reference not set to an instance of an object.
   at ExceptionDemo.Program.<Main>g__fail|0_0() in C:\...\ExceptionDemo\Program.cs:line 12
   at ExceptionDemo.Program.<>c.<Main>g__bareThrow|0_1() in C:\...\ExceptionDemo\Program.cs:line 19
   at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64

Rethrow
----------------------------------------
System.NullReferenceException: Object reference not set to an instance of an object.
   at ExceptionDemo.Program.<>c.<Main>g__rethrow|0_2() in C:\...\ExceptionDemo\Program.cs:line 35
   at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64

Inner Throw
----------------------------------------
System.Exception: outer ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at ExceptionDemo.Program.<Main>g__fail|0_0() in C:\...\ExceptionDemo\Program.cs:line 12
   at ExceptionDemo.Program.<>c.<Main>g__innerThrow|0_3() in C:\...\ExceptionDemo\Program.cs:line 43
   --- End of inner exception stack trace ---
   at ExceptionDemo.Program.<>c.<Main>g__innerThrow|0_3() in C:\...\ExceptionDemo\Program.cs:line 47
   at ExceptionDemo.Program.Main(String[] args) in C:\...\ExceptionDemo\Program.cs:line 64

পূর্ববর্তী উত্তরে উল্লিখিত, খালি নিক্ষেপগুলি স্পষ্টতই কোডের মূল লাইনটি ব্যর্থ করে যা ব্যর্থ হয়েছে (লাইন 12) পাশাপাশি ব্যতিক্রম ঘটলে কল স্ট্যাকটিতে সক্রিয় দুটি অন্যান্য পয়েন্ট (19 এবং 64 লাইন)।

পুনরায় নিক্ষেপের মামলার আউটপুট দেখায় এটি কেন সমস্যা। যখন ব্যতিক্রমটিকে পুনরায় নতুন করে সাজানো হয় তখন ব্যতিক্রমটি মূল স্ট্যাকের তথ্য অন্তর্ভুক্ত করে না। মনে রাখবেন যে কেবলমাত্র throw e(লাইন 35) এবং বহিরাগততম কল স্ট্যাক পয়েন্ট (লাইন 64) অন্তর্ভুক্ত রয়েছে। ব্যর্থতা () পদ্ধতিটিকে সমস্যার উত্স হিসাবে চিহ্নিত করা যদি আপনি এভাবে ব্যতিক্রম ছুঁড়ে ফেলেছেন তবে এটি কঠিন হবে।

শেষ কেসটি (ইনারথ্রো) সর্বাধিক বিস্তৃত এবং উপরের যে কোনওটির চেয়ে বেশি তথ্য অন্তর্ভুক্ত। যেহেতু আমরা একটি নতুন ব্যতিক্রম ইনস্ট্যান্ট করছি, আমরা এখানে প্রাসঙ্গিক তথ্য ("বাহ্যিক" বার্তা) যুক্ত করার সুযোগ পেয়েছি তবে নতুন ব্যতিক্রমের উপর ডেটা অভিধানেও যুক্ত করতে পারি) পাশাপাশি সমস্ত তথ্য সংরক্ষণ করার পাশাপাশি ব্যতিক্রম (সহায়তার লিঙ্ক, ডেটা ডিকশনারি ইত্যাদি সহ)

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.