c#基础之异常处理

摘要:
System.InvalidOperationException当方法调用对对象的当前状态无效时引发的异常。System.InvalidProgramException当程序包含无效的Microsoft中间语言(MSIL)或元数据时引发异常,当无法实现请求的方法或操作时引发System.NotImplementedException。

  在开发过程中,经常遇到各种各样的小问题,很多是由于基础不牢固,没有经常总结导致的。遇到重复的问题可能可根据以往经验处理,但是对问题本身引发的原因进行深入的了解。工作很多年,但是c#基础像一层冰一样,可能还停留在应届生的阶段。

  这里写一些总结帖子,但不会持续写,有时间或者遇到问题时再写,时间比较紧,很多是摘抄网络上的。

  目录(仅记录下):

  c#基础之异常处理

  c#基础之IO操作

  c#基础之对象

  c#基础之特性

c#基础之异常处理 

一、简介

  异常处理是指程序在运行过程中,发生错误会导致程序退出,这种错误,就叫做异常。

  因此处理这种错误,就称为异常处理。

  引起异常的原因,一般是使用者不正当操作,开发者没有按规范的处理数据、使用技术不当导致的,极少情况是由于.NET内部错误引起的。

二、使用

   C# 异常处理时建立在四个关键词之上的:try、catch、finally 和 throw。
   1、try:一个 try 块标识了一个将被激活的特定的异常的代码块。后跟一个或多个 catch 块。
   2、catch:程序通过异常处理程序捕获异常。catch 关键字表示异常的捕获。
   3、finally:finally 块用于执行给定的语句,不管异常是否被抛出都会执行。
   4、throw:当问题出现时,程序抛出一个异常。使用 throw 关键字来完成。

三、C#中的异常类

   C# 异常是使用类来表示的。

   C# 中的异常类主要是直接或间接地派生于System.Exception.

(1).由System.SystemException派生的异常类型:

  System.AccessViolationException 在试图读写受保护内存时引发的异常。

  System.ArgumentException 在向方法提供的其中一个参数无效时引发的异常。

  System.Collections.Generic.KeyNotFoundException 指定用于访问集合中元素的键与集合中的任何键都不匹配时所引发的异常。

  System.IndexOutOfRangeException 访问数组时,因元素索引超出数组边界而引发的异常。

  System.InvalidCastException 因无效类型转换或显示转换引发的异常。

  System.InvalidOperationException 当方法调用对于对象的当前状态无效时引发的异常。

  System.InvalidProgramException 当程序包含无效Microsoft中间语言(MSIL)或元数据时引发的异常,这通常表示生成程序的编译器中有bug。

  System.IO.IOException 发生I/O错误时引发的异常。

  System.NotImplementedException 在无法实现请求的方法或操作时引发的异常。

  System.NullReferenceException 尝试对空对象引用进行操作时引发的异常。

  System.OutOfMemoryException 没有足够的内存继续执行程序时引发的异常。

  System.StackOverflowException 挂起的方法调用过多而导致执行堆栈溢出时引发的异常。

(2).由System.ArgumentException派生的异常类型:

  System.ArgumentNullException 当将空引用传递给不接受它作为有效参数的方法时引发的异常。

  System.ArgumentOutOfRangeException 当参数值超出调用的方法所定义的允许取值范围时引发的异常。

(3).由System.ArithmeticException派生的异常类型:

  System.DivideByZeroException 试图用零除整数值或十进制数值时引发的异常。

  System.NotFiniteNumberException 当浮点值为正无穷大、负无穷大或非数字(NaN)时引发的异常。

  System.OverflowException 在选中的上下文中所进行的算数运算、类型转换或转换操作导致溢出时引发的异常。

(4).由System.IOException派生的异常类型:

  System.IO.DirectoryNotFoundException 当找不到文件或目录的一部分时所引发的异常。

  System.IO.DriveNotFoundException 当尝试访问的驱动器或共享不可用时引发的异常。

  System.IO.EndOfStreamException 读操作试图超出流的末尾时引发的异常。

  System.IO.FileLoadException 当找到托管程序却不能加载它时引发的异常。

  System.IO.FileNotFoundException 试图访问磁盘上不存在的文件失败时引发的异常。

  System.IO.PathTooLongException 当路径名或文件名超过系统定义的最大长度时引发的异常。

(5).其他常用异常类型:   

  ArrayTypeMismatchException 试图在数组中存储错误类型的对象。

  BadImageFormatException 图形的格式错误。

  DivideByZeroException 除零异常。

  DllNotFoundException 找不到引用的dll。

  FormatException 参数格式错误。

  MethodAccessException 试图访问私有或者受保护的方法。

  MissingMemberException 访问一个无效版本的dll。

  NotSupportedException 调用的方法在类中没有实现。

  PlatformNotSupportedException 平台不支持某个特定属性时抛出该错误。

四、深入理解

   示例:

try  
{  
    //一些处理  
}  
catch (Exception e)  
{  
    //一些处理  
    throw e;   //CLR认为这里是异常的起始点  
}  

try  
 {  
     //一些处理  
 }  
 catch (Exception e)  
 {  
     //一些处理  
     throw;  //CLR不会重新设置异常的起始点  
 }  

  设置捕获异常后,再次抛出异常。这种情况很少遇到,一般情况下不会这么处理,但是以上2种方式的处理方式差别很大。

   即当我们抛出一个异常时, CLR会重新设置一个异常起始点。 CLR只记录最近一次异常抛出的位置。

  throw e;  再次引发当前异常,导致CLR重新设置该异常的起始点

  throw  引发当前位于计算堆栈上的异常对象,但不会导致CLR重新设置异常的起始点。

   C#中使用throw和throw ex抛出异常,但二者是有区别的。

   在C#中推荐使用throw;来抛出异常;throw ex;会将到现在为止的所有信息清空,认为你catch到的异常已经被处理了,只不过处理过程中又抛出新的异常,从而找不到真正的错误源。throw e重新抛出异常,并非转发原来的异常,而会更改包括StackTrace在内的许多异常内部信息;对于调用连很深情况,性能损耗超出想象。

 五、Stacktrace(堆栈跟踪)

类:

c#基础之异常处理第1张

网上的代码,记录下以备用

string BuildStackTraceMessage(StackTrace stackTrace)
        {
            if (stackTrace != null)
            {
                var frameList = stackTrace.GetFrames();
                var realFrameList = frameList.Where(i => i.GetMethod().DeclaringType != this.GetType() && i.GetFileLineNumber() > 0);
                if (realFrameList.Any())
                {
                    StringBuilder builder = new StringBuilder();
                    realFrameList = realFrameList.Reverse();
                    var lastFrame = realFrameList.Last();
                    builder.AppendFormat("源文件:{0}", lastFrame.GetFileName()).AppendLine();
                    builder.AppendFormat("行号:{0}", lastFrame.GetFileLineNumber()).AppendLine();
                    builder.AppendFormat("方法名:{0}", lastFrame.GetMethod().ToString()).AppendLine();
                    builder.AppendLine("堆栈跟踪:");
                    builder.AppendLine("=================================================================");

                    MethodBase method;
                    foreach (var frame in realFrameList)
                    {
                        method = frame.GetMethod();
                        builder.AppendFormat("> {0} 类下的第{1}行 {2} 方法", method.DeclaringType.ToString(), frame.GetFileLineNumber(), method.ToString()).AppendLine();
                    }
                    builder.AppendLine("=================================================================");
                    return builder.ToString();
                }
            }
            return "没有堆栈信息";
        }

 C# 获取当前方法的名称空间、类名和方法名称

1.(new StackTrace()).GetFrame(1) // 0为本身的方法;1为调用方法
2.(new StackTrace()).GetFrame(1).GetMethod().Name; // 方法名
3.(new StackTrace()).GetFrame(1).GetMethod().ReflectedType.Name; // 类名

public string GetMethodInfo()
{
    string str = "";

    //取得当前方法命名空间    
    str += "命名空间名:" + System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Namespace + "
";

    //取得当前方法类全名 包括命名空间    
    str += "类名:" + System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + "
";

    //取得当前方法名    
    str += "方法名:" + System.Reflection.MethodBase.GetCurrentMethod().Name + "
"; str += "
";

    //父方法
    System.Diagnostics.StackTrace ss = new System.Diagnostics.StackTrace(true);
    System.Reflection.MethodBase mb = ss.GetFrame(1).GetMethod();

    //取得父方法命名空间    
    str += mb.DeclaringType.Namespace + "
";

    //取得父方法类名    
    str += mb.DeclaringType.Name + "
";

    //取得父方法类全名    
    str += mb.DeclaringType.FullName + "
";

    //取得父方法名    
    str += mb.Name + "
"; return str;
}

相关文章:

使用StackTrace堆栈跟踪记录详细日志(可获取行号)

C# 获取当前方法的名称空间、类名和方法名称

整理的内容来自:

http://www.cnblogs.com/hgmyz/p/6984206.html

http://blog.csdn.net/jiankunking/article/details/49463991

http://blog.csdn.net/jiankunking/article/details/43936729

http://blog.csdn.net/jiankunking/article/details/49443493

免责声明:文章转载自《c#基础之异常处理》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇JS实现定时循环上翻uniapp 类似钉钉的消息时间段显示下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Linux下ffmpeg的完整安装

最近在做一个企业项目, 期间需要将用户上传的视频转成flv格式或mp4格式并用flash插件在前端播放, 我决定采用ffmpeg (http://www.ffmpeg.org/ )实现. 当然以前也用过ffmpeg, 但是没有安装额外的库, 只是源代码下简单地 ./configure, 最后发现好多功能都用不了, 比如最流行的x264编码器. 所以决心完整...

RabbitMQ---6、客户端 API 的简介

1、主要的命名空间,接口和类  定义核心的API的接口和类被定义在RabbitMQ.Client这个命名空间下面:  所以要想使用RabbitMQ的功能,需要以下代码     using RabbitMQ.Client;   【1】、核心API的接口和类如下:    IModel:表示一个符合AMQP 0-9-1 协议的通道,并且提供了很多的操作方法   ...

微信支付什么参数都对,就是提示签名错误的几个可能原因

这次掉到total_fee坑了,参数的类型必须是int类型 1) 使用微信的在线签名工具检查签名是否和程序生成的一致 https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=20_1 签名工具用谷歌打开。 选择MD5,XML,然后把请求参数xml放进去,就能校验签名。 2)如果和微信的在线签名...

用gdb调试nasm汇编程序

用gdb调试nasm汇编程序 对于一个程序员来说,调试是很重要的,可以节约找到bug的时间,不过以前在linux下一直是对c进行调试的,今天突然要对汇编进行调试还真不知道怎么调,特别是对linux下调试汇编程序基本没搞过。记得以前上课学masm时,用的是debug,貌似映像中对汇编挺难调试的。于是就在网上查了下在linux下调试nasm汇编程序的资料,看起...

spring事务注解@Transactional不生效、不回滚原因

一般情况下在方法上直接添加@Transactional即可,但是极有可能会达不到我们想要的效果,这时就需要添加相应的参数,参数如下。 @Transactional(propagation=Propagation.REQUIRED) //控制事务传播。默认是Propagation.REQUIRED  @Transactional(isolation=Iso...

git远程版本回退

本文为博主原创,未经允许不得转载:   之前在git提交版本时,发现将新开发的代码提交到了另一个分支上,为了不影响提交分支代码的 功能,需要回退到之前的版本。   在使用命令回退的时候,一直没有回退成功,有个同事过来帮忙,成功回退到之前的版本,并记录 一下。   查找到git提交时的备注,时间,找到提交时的版本,并方便回退。 同事是在git 小乌龟上进行回...