c# 闲谈异常处理

今天在阅读 .net 源码时发现微软对所有使用枚举类型的地方对枚举值进行了检测,在检测不通过时抛出了异常。

    if (!System.Windows.Forms.ClientUtils.IsEnumValid(value, (int) value, 0, 4))
                {
                    throw new InvalidEnumArgumentException("value", (int) value, typeof(PictureBoxSizeMode));
                }

下面的demo展示了枚举类型的正确使用方法,异常的原因和抛出枚举异常的方法:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };
        static void Main(string[] args)
        {
            try
            {
                ConsoleDay(Days.Fri);   //正确的使用枚举
                ConsoleDay((Days)2);
                ConsoleDay((Days)8);    //枚举异常的来源
            }
            catch (Exception err)
            {
                Console.WriteLine(err.Message);
            }
            Console.ReadLine();
        }
        static void ConsoleDay(Days day)
        {
            int dayInt = (int)day;
            if (dayInt < 0 || dayInt > 6)//检测枚举
            {
                throw new InvalidEnumArgumentException("day", dayInt, typeof(Days));//抛出枚举异常
            }
            Console.WriteLine(day);
        }
    }
}

 关于异常,除了在各个接口中使用 try catch finally 来处理外,还可以对整个程序的异常统一处理。

以 winform 为例,可以修改 program.cs 文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PrintTest
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false); 
            Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);   //处理 UI 线程的异常
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); //处理非 UI 线程的异常
            Application.Run(new Form1());
        }

        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            MessageBox.Show(e.Exception.Message);
        }
        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Console.WriteLine(e.ExceptionObject.ToString());
            MessageBox.Show(e.ExceptionObject.ToString());
        }
    }
}

 我们可以依赖 .net 来生成异常,也可以自己 new 一个异常,这样可以定制异常的 message:

 class Program
    {static void Main(string[] args)
        {
            try
            {
                ConsoleDivision(4, 2);
                ConsoleDivision(4, 0);
            }
            catch (Exception err)
            {
              Console.WriteLine(err.Message);
            }
            Console.ReadLine();
        }

        static void ConsoleDivision(int num1, int num2)
        {
            //if (num2 == 0)
            //{
            //    throw new DivideByZeroException("num2不能是零");
            //}
            Console.WriteLine(num1 / num2);
        }
    }

 当程序的结构较深时需要嵌套异常,使用 new Exception() 的重载,方便定位:

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                DoSomeThing();
            }
            catch (Exception err)
            {
                string innerMsg = err.InnerException == null ? "" : " innerExceptionMessage:" + err.InnerException.Message;
                Console.WriteLine(err.Message + innerMsg);
            }
            Console.ReadLine();
        }

        static void DoSomeThing()
        {
            try
            {
                ConsoleDivision(4, 0);
            }
            catch (Exception err)
            {
                throw new Exception("DoSomeThing异常", err);
            }
        }

        static void ConsoleDivision(int num1, int num2)
        {
            if (num2 == 0)
            {
                throw new DivideByZeroException("num2不能是零啊");
            }
            Console.WriteLine(num1 / num2);
        }
    }

 当需要区分异常时可以使用多个 catch (注意将catch(Exception err)放在最后面,因为 Exception 是所有异常的基类,必然捕获),可以自定义各种类型的异常。

namespace ConsoleApplication1
{
    class MyException : Exception
    {
        public MyException()
            : base()
        {
        }

        public MyException(string str)
            : base(str)
        {
        }

        public MyException(string str, Exception inner)
            : base(str, inner)
        {
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                throw new MyException("");
                //throw new DivideByZeroException();
            }
            catch (MyException err)
            {
                Console.WriteLine("MyException捕获" + err.Message);
            }
            catch (Exception err)
            {
                Console.WriteLine("Exception捕获" + err.Message);
            }

            Console.ReadLine();
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/aitong/p/10536411.html