تفاوت بین Throw و Throw exception در #C
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: چهار دقیقه

یکی از سؤالاتی که ممکن است در مصاحبه‌ها با آن روبرو شوید، عنوان این مطلب است. در این مقاله قصد داریم تفاوت بین این دو را بررسی کنیم.

در علم کامپیوتر، یک call stack، یک ساختار داده‌ای پشته می‌باشد که اطلاعات جزئی را راجع به زیرروال‌های فعال یک برنامه، ذخیره می‌کند. این نوع پشته با اسامی مختلفی از جمله Execution Stack (ES)، Program Stack (PS)، Control Stack، Runtime Stack یا Machine Stack شناخته می‌شود و یا اینکه به صورت کلی به آن The Stack یا همان پشته هم می‌گویند. با استفاده از صفحه Call Stack می­توانیم توابع و پروسیجرهایی را که فراخوانی شده‌اند، ببینیم. Call Stack به ما می‌گوید که کدام متدها و توابع، با چه ترتیبی اجرا شده‌اند. Call Stack یک راه بسیار خوب، برای فهم درست نحوه‌ی اجرای یک برنامه است. با رهگیری یا Track کردن Call Stack می­توانیم بفهمیم که مکانیزم کار داخلی برنامه چگونه است و برای بهتر رفع کردن مشکلات، از آن استفاده کنیم. در سی شارپ، Stack Trace یک پشته‌ی اجرایی یا Execution Stack است که تمامی متدهای درحال اجرا را رهگیری (Track) می‌کند. Stack Trace راهی است که با استفاده از آن می‌توانیم  Call Stack را بررسی کنیم، تا شماره خط متدی را که Exception درآن رخ داده است، ببینیم. از این به بعد برای سادگی مطلب، Stack Trace را به صورت ST بیان می‌کنیم. برای دسترسی به ST از فضای نام System.Diagnostics مانند زیر استفاده می‌کنیم.

System.Diagnostics.StackTrace myTrack = new System.Diagnostics.StackTrace();

و یا برای مشاهده‌ی آن در کنسول از کد زیر استفاده میکنیم:

static void Main(string[] args)
{
    Console.WriteLine("Stack Trace: {0}", Environment.StackTrace);
}

نتیجه:

Stack Trace:at System.Environment.get_StackTrace()
 at DiffThrowAndThrowException.Program.Main(String[] args) in Program.cs:line 9


استفاده از ST در Try Catch :

static void Main(string[] args)
{
  try
  {
     throw new Exception();
  }
  catch (Exception ex)
  {
     Console.WriteLine("Stack Trace: {0}", Environment.StackTrace);
  }
}

نتیجه:

Stack Trace:at System.Environment.get_StackTrace()
 at DiffThrowAndThrowException.Program.Main(String[] args) in Program.cs:line 11


حالا که مفهوم Stack Trace و نحوه کار و نمایش آن را بررسی کردیم، به راحتی می‌توان تفاوت بین Throw و Throw Exception را درک کرد. به طور کلی می‌توان اینطور گفت، در حالتیکه در داخل بلاک Catch، از Throw استفاده کنیم، این کار باعث می‌شود استثنائی که در اینجا رخ داده، به ابتدای ST افزوده شده و در واقع سلسله مراتب اجرای برنامه تا جایی که Throw نوشته شده، در ST نگهداری شود. اما در صورتیکه به جای Throw از Throw Exception استفاده کنیم، اتفاقی که رخ می‌دهد این است که ST تا اینجای کار که throw exception را استفاده می‌کنیم، نگهداری میشود و اطلاعات متدهایی که بعد از throw exception اجرا شده‌اند، از آن حذف می‌شود. در نهایت در این حالت ST شامل اطلاعات متدهای اجرا شده در فرآیند جاری، از ابتدا تا رسیدن به throw exception می‌باشد.

در زیر، نمونه کدی را برای استفاده از Throw، می‌بینید:

    class Program
    {
        static void Main(string[] args)
        {
            FirstExceptionMethod firstException = new FirstExceptionMethod();
            try
            {
                firstException.Method1();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
            }
        }
    }
    class FirstExceptionMethod
    {
        public void Method1()
        {
            try
            {
                SecondExceptionMethod secondException = new SecondExceptionMethod();
                secondException.Method2();
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }
    class SecondExceptionMethod
    {
        public void Method2()
        {
            try
            {
                ThrowExMethod();

            }
            catch (Exception ex)
            {
                throw;
            }
        }
        public void ThrowExMethod()
        {
            throw new Exception();
        }
    }  


نتیجه:

at DiffThrowAndThrowException.SecondExceptionMethod.ThrowExMethod() in Program.cs:line 51
   at DiffThrowAndThrowException.SecondExceptionMethod.Method2() in Program.cs:line 41
   at DiffThrowAndThrowException.FirstExceptionMethod.Method1() in Program.cs:line 27
   at DiffThrowAndThrowException.Program.Main(String[] args) in Program.cs:line 12  

همانطور که می‌بینید اطلاعات متدهایی که در این فرآیند اجرا شده‌اند، در داخل Stack Trace رهگیری (track) شده‌اند.


این دفعه برای نشان دادن تفاوت محتویات ST، کدهای Method1 را به شکل زیر تغییر میدهیم که در بخش catch آن، از throw exception استفاده کرده‌ایم:

public void Method1()
        {
            try
            {
                SecondExceptionMethod secondException = new SecondExceptionMethod();
                secondException.Method2();
            }
            catch (Exception ex)
            {
                throw new Exception("Some Text ...");
            }
        }

نتیجه:

   at DiffThrowAndThrowException.FirstExceptionMethod.Method1() in Program.cs:line 31
   at DiffThrowAndThrowException.Program.Main(String[] args) in Program.cs:line 12

در اینجا اطلاعات متدهای برنامه از شروع فرآیند تا جائیکه از throw exception استفاده کرده، در ST نوشته می‌شود.

با دیدن خروجی‌های بالا می‌توان دریافت که استفاده از throw exception بجای throw باعث می‌شود تا اطلاعات کمتری از فرآیند اجرا شده در ST ذخیره شود و در واقع رهگیری متدهای فرآیند از ابتدا تا جائیکه throw exception استفاده می‌شود، پیش میرود و بعد از آن اطلاعاتی را ثبت نمی‌کند.

  • #
    ‫۳ سال قبل، سه‌شنبه ۲۳ شهریور ۱۴۰۰، ساعت ۱۷:۱۷
    به نظر می‌رسد در قطعه کد سوم اشتباه تایپی رخ داده باشد چون هیچ Exception  ای در Main صادر نشده و لذا خروجی باید چیزی شبیه به این باشد:

    Stack Trace:  at System.Environment.get_StackTrace()
    at Program.Main()

    • #
      ‫۳ سال قبل، سه‌شنبه ۲۳ شهریور ۱۴۰۰، ساعت ۱۷:۳۵
      در قطعه کد سوم نتیجه دقیقا چیزی هست که شما نوشتین و درست می‌فرمایید که هیچ Exception ای صادر نشده. فقط فکر میکنم به خاطر اسم پروژه (DiffThrowAndThrowException) هست که به اشتباه افتادین.
       در واقع ()Program . Main  برابر  DiffThrowAndThrowException . Program . Main ( String [ ] args ) هستش.