Exception 类
TOC
折叠目录
展开目录
本文由机器翻译。若要查看英语原文,请勾选“英语”复选框。 也可将鼠标指针移到文本上,在弹出窗口中显示英语原文。
翻译
英语

Exception 类

 

表示在应用程序执行过程中发生的错误。

若要浏览此类型的.NET Framework 源代码,请参阅 Reference Source

命名空间:   System
程序集:  mscorlib(mscorlib.dll 中)

System.Object
  System.Exception
    Microsoft.Build.BuildEngine.InternalLoggerException
    Microsoft.Build.BuildEngine.InvalidProjectFileException
    Microsoft.Build.BuildEngine.InvalidToolsetDefinitionException
    Microsoft.Build.BuildEngine.RemoteErrorException
    Microsoft.Build.Exceptions.BuildAbortedException
    Microsoft.Build.Exceptions.InternalLoggerException
    Microsoft.Build.Exceptions.InvalidProjectFileException
    Microsoft.Build.Exceptions.InvalidToolsetDefinitionException
    Microsoft.Build.Framework.LoggerException
    Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
    Microsoft.CSharp.RuntimeBinder.RuntimeBinderInternalCompilerException
    Microsoft.JScript.CmdLineException
    Microsoft.JScript.ParserException
    Microsoft.VisualBasic.ApplicationServices.CantStartSingleInstanceException
    Microsoft.VisualBasic.ApplicationServices.NoStartupFormException
    Microsoft.VisualBasic.Compatibility.VB6.WebClassContainingClassNotOptional
    Microsoft.VisualBasic.Compatibility.VB6.WebClassCouldNotFindEvent
    Microsoft.VisualBasic.Compatibility.VB6.WebClassNextItemCannotBeCurrentWebItem
    Microsoft.VisualBasic.Compatibility.VB6.WebClassNextItemRespondNotFound
    Microsoft.VisualBasic.Compatibility.VB6.WebClassUserWebClassNameNotOptional
    Microsoft.VisualBasic.Compatibility.VB6.WebClassWebClassFileNameNotOptional
    Microsoft.VisualBasic.Compatibility.VB6.WebClassWebItemNotValid
    Microsoft.VisualBasic.Compatibility.VB6.WebItemAssociatedWebClassNotOptional
    Microsoft.VisualBasic.Compatibility.VB6.WebItemClosingTagNotFound
    Microsoft.VisualBasic.Compatibility.VB6.WebItemCouldNotLoadEmbeddedResource
    Microsoft.VisualBasic.Compatibility.VB6.WebItemCouldNotLoadTemplateFile
    Microsoft.VisualBasic.Compatibility.VB6.WebItemNameNotOptional
    Microsoft.VisualBasic.Compatibility.VB6.WebItemNoTemplateSpecified
    Microsoft.VisualBasic.Compatibility.VB6.WebItemTooManyNestedTags
    Microsoft.VisualBasic.Compatibility.VB6.WebItemUnexpectedErrorReadingTemplateFile
    Microsoft.VisualBasic.CompilerServices.IncompleteInitialization
    Microsoft.VisualBasic.CompilerServices.InternalErrorException
    Microsoft.VisualBasic.FileIO.MalformedLineException
    System.Activities.DynamicUpdate.InstanceUpdateException
    System.Activities.ExpressionParser.SourceExpressionException
    System.Activities.Expressions.LambdaSerializationException
    System.Activities.InvalidWorkflowException
    System.Activities.Presentation.Metadata.AttributeTableValidationException
    System.Activities.Statements.WorkflowTerminatedException
    System.Activities.VersionMismatchException
    System.Activities.WorkflowApplicationException
    System.AddIn.Hosting.AddInSegmentDirectoryNotFoundException
    System.AddIn.Hosting.InvalidPipelineStoreException
    System.AggregateException
    System.ApplicationException
    System.ComponentModel.Composition.CompositionContractMismatchException
    System.ComponentModel.Composition.CompositionException
    System.ComponentModel.Composition.ImportCardinalityMismatchException
    System.ComponentModel.Composition.Primitives.ComposablePartException
    System.ComponentModel.DataAnnotations.ValidationException
    System.ComponentModel.Design.ExceptionCollection
    System.Configuration.Provider.ProviderException
    System.Configuration.SettingsPropertyIsReadOnlyException
    System.Configuration.SettingsPropertyNotFoundException
    System.Configuration.SettingsPropertyWrongTypeException
    System.Data.Linq.ChangeConflictException
    System.Diagnostics.Eventing.Reader.EventLogException
    System.Diagnostics.Tracing.EventSourceException
    System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectExistsException
    System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectNotFoundException
    System.DirectoryServices.ActiveDirectory.ActiveDirectoryOperationException
    System.DirectoryServices.ActiveDirectory.ActiveDirectoryServerDownException
    System.DirectoryServices.Protocols.DirectoryException
    System.IdentityModel.AsynchronousOperationException
    System.IdentityModel.Metadata.MetadataSerializationException
    System.IdentityModel.Protocols.WSTrust.WSTrustSerializationException
    System.IdentityModel.RequestException
    System.IdentityModel.Selectors.CardSpaceException
    System.IdentityModel.Selectors.IdentityValidationException
    System.IdentityModel.Selectors.PolicyValidationException
    System.IdentityModel.Selectors.ServiceBusyException
    System.IdentityModel.Selectors.ServiceNotStartedException
    System.IdentityModel.Selectors.StsCommunicationException
    System.IdentityModel.Selectors.UnsupportedPolicyOptionsException
    System.IdentityModel.Selectors.UntrustedRecipientException
    System.IdentityModel.Selectors.UserCancellationException
    System.IdentityModel.Services.AsynchronousOperationException
    System.IdentityModel.Services.FederatedAuthenticationSessionEndingException
    System.IdentityModel.Services.FederationException
    System.IdentityModel.Services.WSFederationMessageException
    System.InvalidTimeZoneException
    System.IO.IsolatedStorage.IsolatedStorageException
    System.IO.Log.SequenceFullException
    System.Management.Instrumentation.InstrumentationBaseException
    System.Management.Instrumentation.WmiProviderInstallationException
    System.Net.Http.HttpRequestException
    System.Net.Mail.SmtpException
    System.Net.PeerToPeer.PeerToPeerException
    System.Runtime.CompilerServices.RuntimeWrappedException
    System.Runtime.DurableInstancing.InstancePersistenceException
    System.Runtime.Remoting.MetadataServices.SUDSGeneratorException
    System.Runtime.Remoting.MetadataServices.SUDSParserException
    System.Runtime.Serialization.InvalidDataContractException
    System.Security.RightsManagement.RightsManagementException
    System.ServiceModel.Channels.InvalidChannelBindingException
    System.SystemException
    System.Threading.BarrierPostPhaseException
    System.Threading.LockRecursionException
    System.Threading.Tasks.TaskSchedulerException
    System.TimeZoneNotFoundException
    System.Web.Query.Dynamic.ParseException
    System.Web.Security.MembershipCreateUserException
    System.Web.Security.MembershipPasswordException
    System.Web.UI.ViewStateException
    System.Web.UI.WebControls.EntityDataSourceValidationException
    System.Web.UI.WebControls.LinqDataSourceValidationException
    System.Windows.Automation.NoClickablePointException
    System.Windows.Automation.ProxyAssemblyNotLoadedException
    System.Windows.Controls.PrintDialogException
    System.Windows.Forms.AxHost.InvalidActiveXStateException
    System.Windows.Xps.XpsException
    System.Windows.Xps.XpsWriterException
    System.Workflow.Activities.Rules.RuleException
    System.Workflow.ComponentModel.Compiler.WorkflowValidationFailedException
    System.Workflow.ComponentModel.Serialization.WorkflowMarkupSerializationException
    System.Workflow.ComponentModel.WorkflowTerminatedException
    System.Workflow.Runtime.WorkflowOwnershipException
    System.Xaml.XamlException

[SerializableAttribute]
[ClassInterfaceAttribute(ClassInterfaceType.None)]
[ComVisibleAttribute(true)]
public class Exception : ISerializable, _Exception

名称说明
System_CAPS_pubmethodException()

初始化 Exception 类的新实例。

System_CAPS_protmethodException(SerializationInfo, StreamingContext)

用序列化数据初始化 Exception 类的新实例。

System_CAPS_pubmethodException(String)

用指定的错误消息初始化 Exception 类的新实例。

System_CAPS_pubmethodException(String, Exception)

使用指定的错误消息和对作为此异常原因的内部异常的引用来初始化 Exception 类的新实例。

名称说明
System_CAPS_pubpropertyData

获取提供有关异常的其他用户定义信息的键/值对集合。

System_CAPS_pubpropertyHelpLink

获取或设置指向与此异常关联的帮助文件链接。

System_CAPS_pubpropertyHResult

获取或设置 HRESULT(一个分配给特定异常的编码数字值)。

System_CAPS_pubpropertyInnerException

获取导致当前异常的 Exception 实例。

System_CAPS_pubpropertyMessage

获取描述当前异常的消息。

System_CAPS_pubpropertySource

获取或设置导致错误的应用程序或对象的名称。

System_CAPS_pubpropertyStackTrace

获取调用堆栈上的即时框架字符串表示形式。

System_CAPS_pubpropertyTargetSite

获取引发当前异常的方法。

名称说明
System_CAPS_pubmethodEquals(Object)

确定指定的对象是否等于当前对象。(从 Object 继承。)

System_CAPS_protmethodFinalize()

在垃圾回收将某一对象回收前允许该对象尝试释放资源并执行其他清理操作。(从 Object 继承。)

System_CAPS_pubmethodGetBaseException()

当在派生类中重写时,返回 Exception,它是一个或多个并发的异常的根源。

System_CAPS_pubmethodGetHashCode()

作为默认哈希函数。(从 Object 继承。)

System_CAPS_pubmethodGetObjectData(SerializationInfo, StreamingContext)

当在派生类中重写时,用关于异常的信息设置 SerializationInfo

System_CAPS_pubmethodGetType()

获取当前实例的运行时类型。

System_CAPS_protmethodMemberwiseClone()

创建当前 Object 的浅表副本。(从 Object 继承。)

System_CAPS_pubmethodToString()

创建并返回当前异常的字符串表示形式。(替代 Object.ToString()。)

名称说明
System_CAPS_proteventSerializeObjectState

当异常被序列化用来创建包含有关该异常的徐列出数据的异常状态对象时会出现该问题。

System_CAPS_note注意

若要查看此类型的.NET Framework 源代码,请参阅 Reference Source 您可以浏览源代码、 下载脱机查看参考资料和调试; 在逐句通过源 (包括修补程序和更新)see instructions.

此类是所有异常的基类。 当发生错误时,在系统或当前正在执行的应用程序报告它通过引发异常,其中包含有关错误的信息。 将引发异常后,处理由应用程序或通过默认异常处理程序。

本节内容:

错误和异常
Try/catch 块
异常类型的功能
异常类的属性
性能注意事项
重新引发异常
选择标准异常
实现自定义异常

运行时错误可能的原因有多种。 但是,应在您的代码中作为异常处理不是所有错误。 以下是一些可以发生在运行的时和适当的方式对其进行响应的错误的类别。

  • 用法错误。用法错误表示可能会导致异常的程序逻辑中的错误。 但是,不是通过异常处理,但通过修改了错误代码,则应解决该错误。 例如,重写 Object.Equals(Object) 方法在下面的示例假定 obj 参数必须始终为非 null。

    using System;
    
    public class Person
    {
       private string _name;
    
       public string Name 
       {
          get { return _name; } 
          set { _name = value; }
       }
    
       public override int GetHashCode()
       {
          return this.Name.GetHashCode();  
       }  
    
       public override bool Equals(object obj)
       {
          // This implementation contains an error in program logic:
          // It assumes that the obj argument is not null.
          Person p = (Person) obj;
          return this.Name.Equals(p.Name);
       }
    }
    
    public class Example
    {
       public static void Main()
       {
          Person p1 = new Person();
          p1.Name = "John";
          Person p2 = null; 
    
          // The following throws a NullReferenceException.
          Console.WriteLine("p1 = p2: {0}", p1.Equals(p2));   
       }
    }
    

    NullReferenceException 产生的异常时 objnull 可通过修改源代码来显式测试是否存在之前调用的 null 消除 Object.Equals 重写和重新编译。 下面的示例包含更正的源代码来处理 null 参数。

    using System;
    
    public class Person
    {
       private string _name;
    
       public string Name 
       {
          get { return _name; } 
          set { _name = value; }
       }
    
       public override int GetHashCode()
       {
          return this.Name.GetHashCode();  
       }  
    
       public override bool Equals(object obj)
       {
           // This implementation handles a null obj argument.
           Person p = obj as Person; 
           if (p == null) 
              return false;
           else
              return this.Name.Equals(p.Name);
       }
    }
    
    public class Example
    {
       public static void Main()
       {
          Person p1 = new Person();
          p1.Name = "John";
          Person p2 = null; 
    
          Console.WriteLine("p1 = p2: {0}", p1.Equals(p2));   
       }
    }
    // The example displays the following output:
    //        p1 = p2: False
    

    而不是使用使用错误的异常处理,您可以使用 Debug.Assert 方法来标识在调试版本中的用法错误和 Trace.Assert 方法来标识在调试和发布中的用法错误生成。 有关详细信息,请参阅托管代码中的断言

  • 程序错误数。程序错误是一定不能通过编写无 bug 的代码来避免发生运行时错误。

    在某些情况下,程序错误可能会反映预期或例程错误条件。 在这种情况下,您可能想要避免使用异常处理程序错误处理并改为重试该操作。 例如,如果希望用户在输入中某一特定格式的日期,您可以分析日期字符串通过调用 DateTime.TryParseExact 方法,它返回 Boolean 值,该值指示是否使分析操作成功,而不是使用 DateTime.ParseExact 方法,将引发 FormatException 异常如果日期字符串无法转换为 DateTime 值。 同样,如果用户尝试打开不存在的文件,您可以先调用 File.Exists 方法来检查该文件是否存在且,如果不是,请在提示用户是否他或她想要创建它。

    在其他情况下,程序错误反映了可以在代码中处理意外的错误状态。 例如,即使您已检查,以确保存在的文件,它可能会删除之前可以打开它,或者可能已损坏。 在这种情况下,尝试打开该文件通过实例化 StreamReader 对象或调用 Open 方法可能会引发 FileNotFoundException 异常。 在这些情况下,应使用异常处理程序来从错误中恢复。

  • 系统故障。系统失败是不能以编程方式处理有意义的方式运行时错误。 例如,任何方法可引发 OutOfMemoryException 异常如果公共语言运行时无法分配更多内存。 通常,通过使用异常处理不处理系统故障。 相反,您可能能够使用事件,如 AppDomain.UnhandledException 并调用 Environment.FailFast 方法,以记录异常信息并通知用户在发生故障之前在应用程序终止。

公共语言运行库提供了一个异常处理模型所基于的表示形式异常作为对象,并将程序代码和异常处理代码分离到分 try 块和 catch 块。 可以有一个或多个 catch 块中,每个设计为处理特定类型的异常,或者将一个块可捕获更具体的异常比其他块。

如果应用程序处理的应用程序代码块的执行期间发生的异常,该代码必须放置在 try 语句,称为 try 块。 处理引发的异常的应用程序代码 try 块放在 catch 语句,称为 catch 块。 零个或多 catch 块与之关联 try 块中,并且每 catch 块包括确定它处理的异常的类型的类型筛选器。

当异常发生在 try 块中,系统将搜索关联 catch 阻止,直到它将定位在应用程序代码中,它们出现的顺序 catch 处理该异常的块。 一个 catch 块将处理类型的异常 T 如果在 catch 块的类型筛选器指定 T 或任何类型的 T 派生。 系统停止搜索之后找到了第一个 catch 处理该异常的块。 出于此原因,在应用程序代码 catch 之前,必须指定处理某一类型的块 catch 处理它的基类型,如本节后面的示例所示的块。 处理的 catch 块 System.Exception 最后指定。

如果没有任何 catch 块与当前关联的 try 块处理该异常,且当前 try 块嵌套在其他 try 处于当前调用阻止 catch 与下一个封闭的块 try 块进行搜索。 如果没有 catch 找到用于异常块,则系统的当前调用中搜索前面的嵌套级别。 如果没有 catch 块的当前调用中找到的异常、 调用堆栈中向上传递异常和上一个堆栈帧针对搜索 catch 处理该异常的块。 调用堆栈的搜索继续,直到处理该异常或没有更多的帧调用堆栈上存在。 如果没有找到达到调用堆栈的顶部 catch 处理异常的默认异常处理块对其进行处理并在应用程序终止。

异常类型支持以下功能 ︰

  • 描述错误的用户可读文本。 当发生异常时,运行时将会以通知用户错误的性质,并提供操作建议短信来解决此问题。 此文本消息会一直保留在 Message 异常对象的属性。 在创建异常对象时,可以将文本字符串传递给构造函数来描述该特定异常的详细信息。 如果没有错误 message 参数提供给构造函数,则使用默认的错误消息。 有关更多信息,请参见 Message 属性。

  • 引发异常时的调用堆栈的状态。 StackTrace 属性包含可以用于确定在代码中发生错误的堆栈跟踪。 堆栈跟踪列出所有调用的方法和源文件位置的调用中的行号。

Exception 类包含多个属性可以帮助您识别的代码位置、 类型、 帮助文件和异常的原因 ︰ StackTrace, ,InnerException, ,Message, ,HelpLink, ,HResult, ,Source, ,TargetSite, ,和 Data

两个或多个异常之间存在因果关系时 InnerException 属性如何维护这些信息。 外部异常因响应此内部异常。 处理外部异常的代码可用于从以前的内部异常的信息更恰当地处理错误。 关于异常的补充信息可以存储中的键/值对的集合为 Data 属性。

异常对象的创建过程中传递给构造函数的错误消息字符串应本地化,并通过使用可以从资源文件中提供 ResourceManager 类。 有关本地化资源的详细信息,请参阅 创建桌面应用程序的附属程序集打包和部署桌面应用程序中的资源 主题。

若要向用户提供有关异常发生的原因的大量信息 HelpLink 属性可保存到帮助文件的 URL (或 URN)。

Exception 类使用 HRESULT COR_E_EXCEPTION,其值为 0x80131500。

有关实例的初始属性值的列表 Exception 类,请参阅 Exception 构造函数。

可以引发或正在处理异常会消耗大量系统资源和执行时间。 引发异常,只是为了处理真正异常的情况,不能处理可预知的事件或流控制。 例如,在某些情况下,当你要开发类库,例如可以合理地,如果方法参数无效,因为需要您使用有效的参数来调用的方法引发异常。 无效的方法参数,如果它不是使用错误的结果表示,出现了异常。 相反,如果用户输入无效,因为您可以预期用户偶尔会输入无效的数据确实引发了异常。 相反,提供重试机制,以便用户可以输入有效的输入。 也不应使用异常来处理用法错误。 请改用 断言 以确定并更正用法错误。

如果返回代码是不够的; 此外,确实引发了异常没有转换为异常,则返回代码并不需要定期执行 catch 异常、 忽略它,然后继续进行处理。

在许多情况下,异常处理程序只是想要将异常传递给调用方。 这通常出现在 ︰

  • 反过来包装对.NET Framework 类库或其他类库中的方法的调用的类库。

  • 应用程序或遇到致命的异常的库。 异常处理程序可以记录的异常,并随后重新引发异常。

若要重新引发异常的建议的方法是只需使用 引发 C# 中的语句和 引发 在 Visual Basic 中不包含表达式的语句。 这可确保在该异常传播到调用方时,将保留所有的调用堆栈信息。 下面的示例阐释了这一点。 一个字符串扩展方法 FindOccurrences, ,包装到一个或多个调用 String.IndexOf(String, Int32) 而无需预先验证其参数。

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

public static class Library
{
   public static int[] FindOccurrences(this String s, String f)
   {
      var indexes = new List<int>();
      int currentIndex = 0;
      try {
         while (currentIndex >= 0 && currentIndex < s.Length) {
            currentIndex = s.IndexOf(f, currentIndex);
            if (currentIndex >= 0) {
               indexes.Add(currentIndex);
               currentIndex++;
            }
         }
      }
      catch (ArgumentNullException e) {
         // Perform some action here, such as logging this exception.

         throw;
      }
      return indexes.ToArray();
   }
}

然后,调用方调用 FindOccurrences 两次。 在第二次调用 FindOccurrences, ,调用方传递 null 作为搜索字符串,哪些用例 String.IndexOf(String, Int32) 方法会引发 ArgumentNullException 异常。 处理此异常 FindOccurrences 方法并传递的回调用方。 因为 throw 语句使用不含表达式,该示例输出所示调用堆栈会保留。

public class Example
{
   public static void Main()
   {
      String s = "It was a cold day when...";
      int[] indexes = s.FindOccurrences("a");
      ShowOccurrences(s, "a", indexes);
      Console.WriteLine();

      String toFind = null;
      try {
         indexes = s.FindOccurrences(toFind);
         ShowOccurrences(s, toFind, indexes);
      }
      catch (ArgumentNullException e) {
         Console.WriteLine("An exception ({0}) occurred.",
                           e.GetType().Name);
         Console.WriteLine("Message:\n   {0}\n", e.Message);
         Console.WriteLine("Stack Trace:\n   {0}\n", e.StackTrace);
      }
   }

   private static void ShowOccurrences(String s, String toFind, int[] indexes)
   {
      Console.Write("'{0}' occurs at the following character positions: ",
                    toFind);
      for (int ctr = 0; ctr < indexes.Length; ctr++)
         Console.Write("{0}{1}", indexes[ctr],
                       ctr == indexes.Length - 1 ? "" : ", ");

      Console.WriteLine();
   }
}
// The example displays the following output:
//    'a' occurs at the following character positions: 4, 7, 15
//
//    An exception (ArgumentNullException) occurred.
//    Message:
//       Value cannot be null.
//    Parameter name: value
//
//    Stack Trace:
//          at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
//    ngComparison comparisonType)
//       at Library.FindOccurrences(String s, String f)
//       at Example.Main()

与之相反,如果通过使用重新引发异常

throw e

不保留语句中,完整的调用堆栈,并且该示例将生成以下输出 ︰

'a' 发生在以下字符的位置 ︰ 4、 7、 15 出现异常 (ArgumentNullException)。 消息 ︰ 值不能为 null。 参数名称 ︰ 值堆栈跟踪 ︰ 在 Example.Main() Library.FindOccurrences (字符串 s,字符串 f)

稍有比较麻烦的替代方法是引发一个新的异常,并保留在内部异常的原始异常的调用堆栈信息。 然后,调用方可以使用新异常 InnerException 属性来检索堆栈帧和有关原始异常的其他信息。 在这种情况下,在 throw 语句是 ︰

throw new ArgumentNullException("You must supply a search string.",
                                e);

处理异常的用户代码必须知道 InnerException 属性包含有关原始异常的信息,如下面的异常处理程序所示。

try {
   indexes = s.FindOccurrences(toFind);
   ShowOccurrences(s, toFind, indexes);
}
catch (ArgumentNullException e) {
   Console.WriteLine("An exception ({0}) occurred.",
                     e.GetType().Name);
   Console.WriteLine("   Message:\n{0}", e.Message);
   Console.WriteLine("   Stack Trace:\n   {0}", e.StackTrace);
   Exception ie = e.InnerException;
   if (ie != null) {
      Console.WriteLine("   The Inner Exception:");
      Console.WriteLine("      Exception Name: {0}", ie.GetType().Name);
      Console.WriteLine("      Message: {0}\n", ie.Message);
      Console.WriteLine("      Stack Trace:\n   {0}\n", ie.StackTrace);
   }
}
// The example displays the following output:
//    'a' occurs at the following character positions: 4, 7, 15
//
//    An exception (ArgumentNullException) occurred.
//       Message: You must supply a search string.
//
//       Stack Trace:
//          at Library.FindOccurrences(String s, String f)
//       at Example.Main()
//
//       The Inner Exception:
//          Exception Name: ArgumentNullException
//          Message: Value cannot be null.
//    Parameter name: value
//
//          Stack Trace:
//          at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
//    ngComparison comparisonType)
//       at Library.FindOccurrences(String s, String f)

如果必须引发异常,通常可以使用.NET Framework 而不是实现一个自定义异常中的现有异常类型。 您应使用这两个条件下的标准异常类型 ︰

  • 将引发异常认为引起用法错误 (即,由所做的开发人员正在调用您的方法的程序逻辑中的错误)。 通常情况下,将引发异常如 ArgumentException, ,ArgumentNullException, ,InvalidOperationException, ,或 NotSupportedException 该字符串时提供给异常对象的构造函数实例化的异常对象应描述该错误,以便开发人员可修复问题。 有关更多信息,请参见 Message 属性。

  • 您正处理的错误可以传递给调用方与现有的.NET Framework 异常。 您应派生程度最高尽可能引发异常。 例如,如果方法需要一个参数是枚举类型的有效成员,则应引发 InvalidEnumArgumentException (大多数派生类) 而不是以 ArgumentException

下表列出常见的异常类型以及在其下会引发它们的条件。

例外

条件

ArgumentException

传递给方法的非 null 参数无效。

ArgumentNullException

传递给方法的参数是 null

ArgumentOutOfRangeException

参数是有效的值的范围之外。

DirectoryNotFoundException

目录路径的一部分是无效的。

DivideByZeroException

一个整数中的分母或 Decimal 除法运算为零。

DriveNotFoundException

驱动器不可用或不存在。

FileNotFoundException

文件不存在。

FormatException

值不在相应的格式无法转换从字符串转换方法如 Parse

IndexOutOfRangeException

索引是超出界限的数组或集合。

InvalidOperationException

方法调用在对象的当前状态无效。

KeyNotFoundException

找不到指定的键,用于访问集合中的成员。

NotImplementedException

未实现的方法或操作。

NotSupportedException

不支持的方法或操作。

ObjectDisposedException

对已释放的对象执行的操作。

OverflowException

执行算术、 强制转换或转换运算导致溢出。

PathTooLongException

路径或文件的名称超过了系统定义的最大长度。

PlatformNotSupportedException

在当前平台上不支持该操作。

RankException

具有错误维数的数组传递给方法。

TimeoutException

分配给某项操作的时间间隔已过期。

UriFormatException

使用无效的统一资源标识符 (URI)。

在以下情况下,使用现有的.NET Framework 异常以处理错误条件不能满足 ︰

  • 当异常反映了无法映射到现有的.NET Framework 异常的唯一程序错误。

  • 必须从一个类似的异常消除多义性异常要求处理的是不同于适用于现有的.NET Framework 异常或异常的处理。 例如,如果您的函数引发 ArgumentOutOfRangeException 异常分析的数值表示形式超出目标整型类型的范围的字符串时,您不想要从调用方不提供相应的结果受约束的错误值调用该方法时使用相同的异常。

Exception 类是.NET Framework 中的所有异常的基类。 许多派生的类依赖于继承的成员的行为 Exception 类; 它们不会重写的成员 Exception, ,也不定义任何唯一的成员。

若要定义您自己的异常类 ︰

  1. 定义一个类,继承自 Exception 如有必要,定义任何需要根据您的类用于提供有关异常的其他信息的唯一成员。 例如, ArgumentException 类包括 ParamName 指定其参数导致了异常,该参数的名称的属性和 RegexMatchTimeoutException 属性包括 MatchTimeout 属性,它指示在超时间隔。

  2. 如有必要,重写所有继承的成员你想要更改或修改其功能。 请注意,大多数现有的派生类 Exception 不重写继承成员的行为。

  3. 确定您的自定义异常对象是可序列化。 序列化使您可以保存有关异常的信息,并允许异常信息的服务器和客户端代理由远程处理上下文中共享。 若要使异常对象可序列化,将其与标记 SerializableAttribute 属性。

  4. 定义异常类的构造函数。 通常情况下,异常类都有一个或多个以下构造函数 ︰

下面的示例说明了使用自定义异常类。 它定义了 NotPrimeException 客户端尝试通过指定不是素数起始数字中检索的质数序列时,将引发的异常。 该异常中定义新属性, NonPrime, ,返回非质数数字引发异常的异常。 除了实现受保护的无参数构造函数和一个构造函数与 SerializationInfoStreamingContext 参数对于序列化, NotPrimeException 类定义了三个附加的构造函数,以支持 NonPrime 属性。 每个构造函数调用基类构造函数除了保留值的非质数数字。 NotPrimeException 类还具有 SerializableAttribute 属性。

using System;
using System.Runtime.Serialization;

[Serializable()]
public class NotPrimeException : Exception
{
   private int notAPrime;

   protected NotPrimeException()
      : base()
   { }

   public NotPrimeException(int value) :
      base(String.Format("{0} is not a prime number.", value))
   {
      notAPrime = value;
   }

   public NotPrimeException(int value, string message)
      : base(message)
   {
      notAPrime = value;
   }

   public NotPrimeException(int value, string message, Exception innerException) :
      base(message, innerException)
   {
      notAPrime = value;
   }

   protected NotPrimeException(SerializationInfo info,
                               StreamingContext context)
      : base(info, context)
   { }

   public int NonPrime
   { get { return notAPrime; } }
}

PrimeNumberGenerator 类在下面的示例所示使用选筛法求质数来计算素数从 2 到限制对其类构造函数的调用中的客户端指定的序列。 GetPrimesFrom 方法返回大于或等于指定的下限值的所有素数,但会引发 NotPrimeException 如果该较低的限制不是素数。

using System;
using System.Collections.Generic;


[Serializable]
public class PrimeNumberGenerator
{
   private const int START = 2;
   private int maxUpperBound = 10000000;
   private int upperBound;
   private bool[] primeTable;
   private List<int> primes = new List<int>();

   public PrimeNumberGenerator(int upperBound)
   {
      if (upperBound > maxUpperBound)
      {
         string message = String.Format(
                           "{0} exceeds the maximum upper bound of {1}.",
                           upperBound, maxUpperBound);
         throw new ArgumentOutOfRangeException(message);
      }
      this.upperBound = upperBound;
      // Create array and mark 0, 1 as not prime (True).
      primeTable = new bool[upperBound + 1];
      primeTable[0] = true;
      primeTable[1] = true;

      // Use Sieve of Eratosthenes to determine prime numbers.
      for (int ctr = START; ctr <= (int)Math.Ceiling(Math.Sqrt(upperBound));
            ctr++)
      {
         if (primeTable[ctr]) continue;

         for (int multiplier = ctr; multiplier <= upperBound / ctr; multiplier++)
            if (ctr * multiplier <= upperBound) primeTable[ctr * multiplier] = true;
      }
      // Populate array with prime number information.
      int index = START;
      while (index != -1)
      {
         index = Array.FindIndex(primeTable, index, (flag) => !flag);
         if (index >= 1)
         {
            primes.Add(index);
            index++;
         }
      }
   }

   public int[] GetAllPrimes()
   {
      return primes.ToArray();
   }

   public int[] GetPrimesFrom(int prime)
   {
      int start = primes.FindIndex((value) => value == prime);
      if (start < 0)
         throw new NotPrimeException(prime, String.Format("{0} is not a prime number.", prime));
      else
         return primes.FindAll((value) => value >= prime).ToArray();
   }
}

下面的示例调用两 GetPrimesFrom 方法与非质数,其中一个跨越应用程序域边界。 在这两种情况下,该异常引发并成功地在客户端代码中处理。

using System;
using System.Reflection;

class Example
{
   public static void Main()
   {
      int limit = 10000000;
      PrimeNumberGenerator primes = new PrimeNumberGenerator(limit);
      int start = 1000001;
      try
      {
         int[] values = primes.GetPrimesFrom(start);
         Console.WriteLine("There are {0} prime numbers from {1} to {2}",
                           start, limit);
      }
      catch (NotPrimeException e)
      {
         Console.WriteLine("{0} is not prime", e.NonPrime);
         Console.WriteLine(e);
         Console.WriteLine("--------");
      }

      AppDomain domain = AppDomain.CreateDomain("Domain2");
      PrimeNumberGenerator gen = (PrimeNumberGenerator)domain.CreateInstanceAndUnwrap(
                                        typeof(Example).Assembly.FullName,
                                        "PrimeNumberGenerator", true,
                                        BindingFlags.Default, null,
                                        new object[] { 1000000 }, null, null);
      try
      {
         start = 100;
         Console.WriteLine(gen.GetPrimesFrom(start));
      }
      catch (NotPrimeException e)
      {
         Console.WriteLine("{0} is not prime", e.NonPrime);
         Console.WriteLine(e);
         Console.WriteLine("--------");
      }
   }
}

在 适用于 Windows 8.x 应用商店应用的 .NET 为 Windows 8, ,通过非.NET Framework 的堆栈帧传播异常时会通常丢失某些异常信息。 从开始 .NET Framework 4.5.1 和 Windows 8.1, ,公共语言运行时将继续使用原始 Exception 已引发,除非该异常在.NET Framework 堆栈帧中修改的对象。

下面的示例演示 catch 块定义为处理 ArithmeticException 错误。catch 块还捕捉 DivideByZeroException 错误,因为 DivideByZeroException 派生自 ArithmeticException ,并且没有任何 catch 显式定义为块 DivideByZeroException 错误。

using System;

class ExceptionTestClass 
{
   public static void Main() 
   {
      int x = 0;
      try 
      {
         int y = 100/x;
      }
         catch (ArithmeticException e) 
         {
            Console.WriteLine("ArithmeticException Handler: {0}", e.ToString());
         }
         catch (Exception e) 
         {
            Console.WriteLine("Generic Exception Handler: {0}", e.ToString());
         }
   }	
}
/*
This code example produces the following results:

ArithmeticException Handler: System.DivideByZeroException: Attempted to divide by zero.
   at ExceptionTestClass.Main()

*/

Universal Windows Platform
8 后可用
.NET Framework
1.1 后可用
Portable Class Library
受以下版本支持:portable .NET platforms
Silverlight
2.0 后可用
Windows Phone Silverlight
7.0 后可用
Windows Phone
8.1 后可用

此类型的任何公共静态(Visual Basic 中为 Shared)成员都是线程安全的。但不保证所有实例成员都是线程安全的。

返回页首
显示:
© 2016 Microsoft