沂源放心企业网站建设方案报价,怎么开公众号微信,衡水自助建站系统,网站的优化从几个方面常见的C#xff03;异常及其修复方法如果您今天是依靠编写的软件来谋生#xff0c;那么您可能至少对异常的概念很熟悉。Jeff Atwood曾经称它们为“现代编程语言的基础”。异常[1]是现代软件开发中常见且有用的结构#xff0c;但有时它们也可能造成混乱。那么什么是异常… 常见的C异常及其修复方法如果您今天是依靠编写的软件来谋生那么您可能至少对异常的概念很熟悉。Jeff Atwood曾经称它们为“现代编程语言的基础”。异常[1]是现代软件开发中常见且有用的结构但有时它们也可能造成混乱。那么什么是异常更具体地说C异常的主要类型是什么以及如何使用它们今天的帖子将回答上述问题以及更多问题。我们将从“异常”的简要定义开始然后继续解释该结构的组成部分。最后我们将概述最常见的C异常以及如何处理它们。让我们开始吧。有什么异常异常是一种可用于处理错误的机制。就这么简单。在某些情况下例如C程序员将返回错误代码而Java[2]或C程序员都很有可能引发异常。异常表示执行流程的突然中断。一旦引发异常执行就会停止。如果未处理异常则应用程序崩溃。但是实际上您是如何做到的呢您如何引发或捕获异常所有这些甚至意味着什么这就是我们将在下一部分中详细介绍的内容。C异常剖析现在我们将简要介绍C异常的情况。您将了解应该使用的主要关键字这些关键字不仅可以捕获和处理异常还可以抛出自己的异常。我们列表上的第一个是try关键字和块。try异常处理解剖的第一部分是try块。您可以使用它来尝试执行一些可能引发异常的代码。考虑以下代码摘录string content string.Empty;
try
{content System.IO.File.ReadAllText(C:\file.txt);
}
上面的代码声明了一个变量并为其分配了空字符串。然后我们有了try块。块中的单行代码try使用该类中的ReadAllText静态方法System.IO.File。我们担心该路径表示的文件可能不存在在这种情况下会引发异常。但是当然这还不够。我们的代码不执行任何处理异常的操作。它甚至目前还没有编译这是来自编译器的消息Expected catch or finally
该消息是不言自明的。我们需要 catch或finally代码块因为尝试处理异常然后忘记执行处理部分没有任何意义。让我们开始吧。catchcatch代码块使我们能够实际处理异常。我们将使用更多代码扩展前面的示例。看看这个 static void Main(string[] args){string content string.Empty;try{Console.WriteLine(First message inside try block.);Console.WriteLine(Second message inside try block.);content System.IO.File.ReadAllText(C:\file.txt);Console.WriteLine(Third message inside try block. This shouldnt be printed.);}catch{Console.WriteLine(First message inside the catch block.);Console.WriteLine(Second message inside the catch block.);}Console.WriteLine(Outside the try-catch.);Console.ReadLine();}
如果运行上面的代码则应看到以下内容First message inside try block.
Second message inside try block.
First message inside the catch block.
Second message inside the catch block.
Outside try-catch.
该路径处的文件不存在因此将引发System.FileNotFoundException。发生这种情况时执行流程将立即中断。因此将在try块中打印“第三条消息”的行。这不应该被打印。” 永远不会被执行。执行流程由catch块执行。完成后将控制权交还给main方法然后打印Outside try-catch。并等待用户输入。最后在了解了try和之后catch我们终于没有双关语准备好使用这个非常有用但经常被误解的异常处理机制的一部分。那么什么是finally该finally块是一种确保将执行给定代码段的方式无论是否引发异常。考虑下面的代码try
{content System.IO.File.ReadAllText(path);Console.WriteLine(If youre reading this, no exception was thrown.);
}
catch (System.IO.FileNotFoundException e)
{Console.WriteLine(If youre reading this, an exception was thrown.);Console.WriteLine(Message: e.Message);
}
finally
{Console.WriteLine(This will be printed, no matter what.);
}
那仍然是相同的示例但是现在要简单得多。注意最后的finally块。如果运行此代码则应该看到以下消息If youre reading this, an exception was thrown.
Message: Could not find file C:\file.txt.
This will be printed, no matter what.
Outside the try-catch.
现在让我们模拟文件的存在。注释掉试图从文件中读取的行然后再次运行该应用程序。这是您现在应该看到的If youre reading this, no exception was thrown.
This will be printed, no matter what.
Outside the try-catch.
如您所见在最近的场景中没有引发异常因此该catch块中没有执行任何行。另一方面finally在两种情况下都执行了该块。throw当涉及到异常时您将不会总是从别人那里处理它们。您也可以自己抛出异常。为此您将使用throw关键字然后是要引发的异常的类的实例化。以下代码举例说明了这一点public ProductService(IProductRepository repository)
{if (repository null)throw new ArgumentNullException();this.repository repository;
}
常见的.NET异常以下是常见的.NET异常列表System.NullReferenceException这是最著名的甚至是臭名昭著的异常之一。当您尝试调用方法/属性/索引器/等时抛出此异常。在包含空引用的变量即它不指向任何对象。下面的代码将导致空引用异常Person p people.Where(x x.SSN verifySsn).FirstOrDefault();
string name p.Name;
在上面的示例中我们过滤了将每个项目的SSN属性与verifySsnvariable变量进行比较的序列。然后我们使用该FirstOrDefault()方法从序列中仅提取第一项。如果序列不产生任何项目则它将返回该类型的默认值。由于Person是引用类型因此其返回值为null。在下一行我们尝试Name在空引用上取消引用属性。Boom这将空引用异常。这是通常不抛出也不捕获的异常。您不要抛出它因为它毫无意义。如果您想与代码的调用者交流给定方法不接受null作为其参数的有效值则使用的正确异常是System.ArgumentNullException。您如何“修复”此异常简而言之您必须对可为空性小心谨慎。如果您正在编写将由第三方使用的任何代码即使这些第三方是您的同事则请认真考虑是否接受空引用作为有效值。无论您做出什么决定都必须使该决定非常明确并记录在案。您可以通过抛出System.ArgumentNullException例如并在方法上使用XML文档标题来实现。System.IndexOutOfRangeException在应用程序代码通常不会抛出或捕获该异常的意义上该异常与上一个异常类似。那为什么呢好吧当您尝试使用无效的索引值访问数组列表或任何可索引序列中的元素时将引发此异常。一个简单的例子public static void PrintUrlSufix(string url)
{var parts url.Split(.);Console.WriteLine(parts[2]);
}
上面的代码显然希望使用www.acme.com[3]格式的URL 。但是如果只是获得acme.com怎么办为此如果得到Hakuna Matata怎么办是的没错System.IndexOutOfBoundException是的。您如何避免遇到此异常永远不要把事情视为理所当然。永远不要仅仅假设数据将采用正确的格式。做您的尽职调查和检查的东西。System.IO.IOException此C异常具有一个不言自明的名称。这正是您的想法这是IO操作期间发生错误时引发的异常。与前两个异常不同您可能会发现自己不时捕捉或抛出其中一个。本IOException类实际上是一些更具体的异常例如•DirectoryNotFoundException•EndOfStreamException•FileNotFoundException•FileLoadException•PathTooLongException有关的文档IOException建议您尽可能使用更具体的异常而不是更一般的异常。System.Net.WebException此异常与网络有关。如果使用可插拔协议[4]访问网络时发生错误则抛出该错误。[5]处理此异常时请记住验证该Response属性该属性将包含远程主机返回的响应。System.Data.SqlClient.SqlException此异常与数据库特别是SQL Server有关。SQL Server返回错误或警告时将引发该错误。该类具有一个称为的属性Errors该属性是一个包含SqlError该类的一个或多个实例的集合。依次包含有关发生的错误的详细信息。System.StackOverflowException当执行堆栈溢出时抛出此异常这通常意味着递归出错。该代码有太多的嵌套方法调用。事情就是这样这个异常是无法捕获的-至少从.NET 2.0起就没有-这意味着当抛出该异常时您几乎没有其他选择。默认情况下您的过程将被终止。您应该做的而不是捕获此异常的方法是编写代码以防止它首先发生。System.OutOfMemoryException可以说这是最令人困惑的C异常之一[6]。网上有很多资源可以很好地阐明问题[7]但是我将在此处提供一个简短的版本。发生的情况是此异常不涉及可用的物理内存。那么什么时候抛出此异常您知道何时要停车吗因为其他驾驶员未正确停车而不能停车吗如果您只需在停放的汽车之间添加所有可用空间就足以容纳您的车辆。但是目前不可能因为它不是连续的区域。当您获得此内存时这差不多发生了什么。可能有很多可用的总内存但是没有连续的部分可以满足所需的分配。实际上例如如果您尝试将 StringBuilder的MaxCapacity属性扩展到该属性之外则会发生此异常。System.InvalidCastException此异常也具有不言自明的名称。当代码由于未定义强制类型转换而无法从一种类型转换为另一种类型时将引发该错误。以下代码将引发此类型的异常object o 10;
int x (int)o;
这是您通常不会捕获的异常。相反您将以不会发生的方式编写代码。例如以下代码在尝试强制类型转换之前进行类型检查public override bool Equals (object obj )
{if (!obj is Foo)return false;Foo other (Foo)obj;return this.bar other.bar;
}
上面的代码可以使用简化的as操作符[8]在这里我没有进一步具体说明作为一个练习留给读者。无论如何这就是问题您实际上应该尝试做的是避免问题而不是首先进行转换。利用泛型来防止陷入需要强制转换的情况。System.InvalidOperationException像之前的许多其他异常一样这种异常通常是您不会发现的。相反您应该做的是编写不会发生的代码。考虑以下示例var numbers new Listint { 1, 3, 5 };
var firstGreaterThanFive numbers.Where(x x 5).First();
当序列不产生任何结果时将抛出First LINQ扩展方法。如果您知道该序列有时可能不会产生结果-没关系-您应该改用FirstOrDefault。在空序列上调用此方法时将返回序列类型的默认值而不是抛出异常。System.ObjectDisposedException我们将在这篇文章中介绍的最后一个C异常也属于“不应该处理请修复代码”类别。换句话说这是开发人员错误。当您尝试使用已处理的IDisposable[9]进行操作时将引发此异常。此当通常发生在开发者调用DisposeClose或其它类似方法和后来试图访问该对象的一个成员时。如何成功的进行异常处理错误处理是软件开发教学中经常被忽略的话题出现异常有时非常不幸。如果没有可靠的错误处理策略[10]您的应用程序有可能质量会不过关。通过本文我们希望通过定义异常的概念并对C异常的主要类型进行快速概述以帮助解决该问题。但本文并没有涵盖异常处理的全部。恰好相反我认为这是一个机会可以开始引导您对该主题的学习并且永不停止学习和练习。祝您能想出一种对您的应用程序有效的策略References[1] 异常: https://raygun.com/blog/java-exceptions-terminology/[2] Java: https://raygun.com/blog/java-exceptions-terminology/[3] www.acme.com: http://www.acme.com[4] 可插拔协议: https://docs.microsoft.com/dotnet/framework/network-programming/introducing-pluggable-protocols[5] 。: https://docs.microsoft.com/dotnet/framework/network-programming/introducing-pluggable-protocols[6] 最令人困惑的C异常之一: https://stackoverflow.com/questions/1153702/system-outofmemoryexception-was-thrown-when-there-is-still-plenty-of-memory-fr[7] 可以很好地阐明问题: https://blogs.msdn.microsoft.com/ericlippert/2009/06/08/out-of-memory-does-not-refer-to-physical-memory/[8] as操作符: https://docs.microsoft.com/dotnet/csharp/language-reference/keywords/as[9] IDisposable: https://docs.microsoft.com/dotnet/api/system.idisposable?viewnetframework-4.7.2[10] 错误处理策略: https://raygun.com/blog/errors-and-exceptions/