zoukankan      html  css  js  c++  java
  • 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();
            }
        }
    }
  • 相关阅读:
    TCP握手建立与释放连接
    Oracle Golden Gate概要
    Hadoop Spark 基础教程
    #npm install# MSBUILD : error MSB4132: 无法识别工具版本“2.0”。可用的工具版本为 "4.0"。
    MySQL5.7 不同操作系统下的主从配置
    MongoDB authentication failed
    maven相关基础
    一次失败的定点漏洞挖掘之代码审计宜信Davinci
    记一次在tp5代码执行下的pcntl_exec瞎操作
    【CVE-2020-1957】shiro搭配spring时身份验证绕过漏洞分析
  • 原文地址:https://www.cnblogs.com/aitong/p/10536411.html
Copyright © 2011-2022 走看看