【所见即所得】Try Catch 效率问题

 

 

 

一、问题引入 

     维护老项目,看到下面一个函数:

    /// <summary>

    /// 从ViewState中获取某个属性的值。如果该属性不存在,返回空字符串。



    /// </summary>

    /// <param name="PropertyName">属性名称</param>

    /// <returns>属性值(属性不存在时返回空字符串)</returns>

    protected string GetViewState(string PropertyName)

    {

        try

        {

            return ViewState[PropertyName].ToString();

        }

        catch (NullReferenceException)

        {

            return "";

        }

    }

二、问题分析

     代码功能很明显“从ViewState中获取某个属性的值。如果该属性不存在,返回空字符串。”。看起来也很整洁,想起以前在园子类看到的讨论try-catch的性能问题,基本上已经有定论。自己想验证下:

    测试的类代码如下:

 public  class TryCatch {

      static Stopwatch sw = new Stopwatch();

       /// <summary>

       /// 带有finally的try引发异常来完成字符串赋值

       /// </summary>

       /// <param name="str">传入参数,调用的时候会是null</param>

       /// <returns></returns>

      public static string TryCatchwithFinally(string str) {

          sw.Reset();

          sw.Start();

          try {

              return str.ToString();

          }

          catch (NullReferenceException) {

              return "exception!";

          }

          finally {

              sw.Stop();

              Console.WriteLine("发生exception,带finally的trycatch用时{0}毫秒",sw.ElapsedMilliseconds);

          }

      }

      /// <summary>

      /// 带有finally的try不引发异常通过ifelse来完成字符串赋值

      /// </summary>

      /// <param name="str">传入参数,调用的时候会是null</param>

      /// <returns></returns>

      public static string IfElsewithFinally(string str) {

          sw.Reset();

          sw.Start();

          try {

              if (!string.IsNullOrEmpty(str)) {

                  return str.ToString();

              }

              else {

                  return "";

              }



          }

          catch (NullReferenceException) {

              return "exception!";

          }

          finally {

              sw.Stop();

              Console.WriteLine("不发生exception,带finally得ifelse用时{0}毫秒", sw.ElapsedMilliseconds);

          }

      }

      /// <summary>

      ///  不带有finally的try不引发异常通过ifelse来完成字符串赋值

      /// </summary>

      /// <param name="str">传入参数,调用的时候会是null</param>

      /// <returns></returns>

      public static string IfElse(string str) {

          sw.Reset();

          sw.Start();

          try {

              if (!string.IsNullOrEmpty(str)) {

                  return str.ToString();

              }

              else {

                  sw.Stop();

                  Console.WriteLine("发生exception,ifelse用时{0}毫秒", sw.ElapsedMilliseconds);

                  return "";

              }

          }

          catch (NullReferenceException) {

             

              return "exception!";

        

          }

        

      }

      /// <summary>

      /// 不带有finally的try引发异常来完成字符串赋值

      /// </summary>

      /// <param name="str">传入参数,调用的时候会是null</param>

      /// <returns></returns>

      public static string Trycatch(string str) {

          sw.Reset();

          sw.Start();

          try {

              return str.ToString();

          }

          catch (NullReferenceException) {

              sw.Stop();

              Console.WriteLine("发生exception,trycatch用时{0}毫秒", sw.ElapsedMilliseconds);

              return "exception!";

             

          }



      }

    }

主调函数如下:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using FMS_Refacting.try_catch;





namespace Fibo.ConsoleApplication {

        class Program {

            static void Main(string[] args) {



                TryCatch.IfElsewithFinally(null);//1

                TryCatch.Trycatch(null);//2

                TryCatch.TryCatchwithFinally(null);//3               

                TryCatch.IfElse(null);//3

                Console.ReadKey();



            }

        

    }

   

}

 

   结果如下:

image

 

  将主调函数main中4个语句调换顺序,得到的测试结果大体相同。也就是,用trycatch实现逻辑(简单的)耗时在100毫秒(这个有可能不太准确,不过大约在100倍左右)以上,而ifelse基本不耗时。同一类型的异常被第一次抛出的时候性能会下降很多,而在后续抛出则基本没有影响,CLR在异常处理的这一点进行了强大的优化。

  同时finally中如果没有什么复杂的逻辑的话并不会影响性能。

  下面是 imfunny兄一些高见:

这个结论貌似不对的。
和复杂的逻辑其实没有什么关系。所以楼主改正下呢。
缺少了finally 实际上就缺少了ret的分界表,于是就导致了对异常类型以及异常类型的匹配过程。而这个部分才是耗时的。
 

 

finally 即使有复杂的逻辑也没有关系。这个其实是代码执行的时间。比如有些对资源进行回收导致的代的回收等。
实际上catch过程可用可不用。如果不用可以再Application扑捉到嘿嘿。

  当然为了美观和可读性,ifelse可以用?:和??来代替。

 

三、所得

    对trycatch的运用;只控制异常,不控制逻辑。

    坚信:过度的设计是犯罪,不设计更是犯罪!

    知道了,并运用了Stopwatch类;

   以后继续所见即所得的学习!

 

PS:  在园子里面找到了金大侠的大作:深入理解CLR异常处理机制(http://www.cnblogs.com/bitfan/archive/2009/12/03/1616550.html)。从原理上讲的已经很透彻了。

你可能感兴趣的:(catch)