Questions tagged «exceptions»

例外是在应用程序过程中发生,需要偏离程序的正常流程。

9
为什么许多异常消息不包含有用的详细信息?
似乎在一定程度上同意异常消息应包含有用的细节。 为什么系统组件中的许多常见异常不包含有用的详细信息? 一些例子: .NET List索引访问ArgumentOutOfRangeException并没有告诉我这是尝试和无效的索引值,也不会告诉我的允许范围。 基本上,来自MSVC C ++标准库的所有异常消息都是完全无用的(与上述相同)。 甲骨文例外.NET,告诉你(意译)“表或视图未找到”,但没有哪一个。 因此,在我看来,在大多数情况下,异常消息没有包含足够有用的细节。我的期望与众不同吗?我是否使用异常错误而我甚至注意到了这一点?或者,也许我的印象是错误的:大多数的异常都实际提供有用的信息?
220 c#  c++  exceptions 

22
空引用真的是一件坏事吗?
我听说它说在编程语言中包含空引用是“十亿美元的错误”。但为什么?当然,它们会导致NullReferenceExceptions,但是那又如何呢?如果使用不当,该语言的任何元素都可能成为错误的来源。 还有什么选择?我想不是这样说: Customer c = Customer.GetByLastName("Goodman"); // returns null if not found if (c != null) { Console.WriteLine(c.FirstName + " " + c.LastName + " is awesome!"); } else { Console.WriteLine("There was no customer named Goodman. How lame!"); } 您可以这样说: if (Customer.ExistsWithLastName("Goodman")) { Customer c = Customer.GetByLastName("Goodman") // throws error …

9
作为控制流的例外是否被认为是严重的反模式?如果是这样,为什么?
上世纪90年代后期,我在使用例外作为流控制的代码库中做了很多工作。它实现了一个有限状态机来驱动电话应用程序。最近,我想起那些日子,因为我一直在做MVC Web应用程序。 它们都具有Controllers,该s确定下一个下一步并将数据提供给目标逻辑。来自老式电话域的用户操作(例如DTMF音调)成为操作方法的参数,但是他们没有返回类似a的内容ViewResult,而是抛出了a StateTransitionException。 我认为主要区别在于动作方法是void功能。我不记得我对这个事实所做的所有事情,但是我一直犹豫要记住多少东西,因为自从15年前从事这项工作以来,我再也没有在生产代码中见过任何其他工作。我以为这是一个所谓的反模式迹象。 是这样吗?如果是,为什么? 更新:当我问这个问题时,我已经想到了@MasonWheeler的答案,所以我选择了最能增加我的知识的答案。我认为他也是一个正确的答案。

13
输入在技术上有效但不满意时,异常与空结果集
我正在开发要公开发布的库。它包含用于对对象集进行操作的各种方法-生成,检查,分区并将这些集投影到新形式。如果相关,它是一个C#类库,其中包含LINQ样式的扩展IEnumerable,将作为NuGet软件包发布。 该库中的某些方法可能会被赋予无法满足的输入参数。例如,在组合方法中,存在一种生成可以从m个项目的源集合构造的n个项目的所有集合的方法。例如,给定集合: 1,2,3,4,5 并要求2的组合将产生: 1,2 1,3 1,4 等... 5,3 5,4 现在,显然可以要求做一些无法完成的事情,例如给它提供3个项目的集合,然后要求4个项目的组合,同时设置说只能使用每个项目一次的选项。 在这种情况下,每个参数都是单独有效的: 源集合不为null,并且包含项 要求的组合大小为正非零整数 请求的模式(仅使用每个项目一次)是有效选择 但是,将这些参数的状态放在一起时会引起问题。 在这种情况下,您是否希望该方法引发异常(例如InvalidOperationException)或返回空集合?在我看来,任何一种都有效: 如果只允许每个项目使用一次,则不能从m个项目的集合(其中n> m个)中产生n个项目的组合,因此该操作被认为是不可能的。InvalidOperationException 当n> m时可以从m个项目中生成的大小为n的组合的集合为空集;无法产生任何组合。 空集的参数 我首先担心的是,当您处理大小可能未知的数据集时,异常会阻止惯用的LINQ样式方法链接。换句话说,您可能想要执行以下操作: var result = someInputSet .CombinationsOf(4, CombinationsGenerationMode.Distinct) .Select(combo => /* do some operation to a combination */) .ToList(); 如果您的输入集大小可变,则此代码的行为是不可预测的。如果少于4个元素.CombinationsOf()时引发异常someInputSet,则此代码有时会在运行时失败,而无需进行一些预检查。在上面的示例中,此检查是微不足道的,但是如果您在较长的LINQ链中途调用它,则可能会变得乏味。如果它返回一个空集,result则将为空,您可能会很满意。 例外的论点 我的第二个担心是,返回一个空集可能会隐藏问题-如果您在LINQ链的中途调用此方法,并且它悄悄地返回一个空集,那么稍后可能会遇到问题,或者发现自己为空结果集,鉴于您肯定在输入集中有某些内容,这种情况的发生可能并不明显。 您会期望什么,您对此有何看法?

7
如何编写好的异常消息
我当前正在进行代码审查,并且我注意到的一件事是,异常消息似乎只是在重申发生异常的地方的异常数量。例如 throw new Exception("BulletListControl: CreateChildControls failed."); 我可以从其余消息中得出此消息中的所有三个项目。我从堆栈跟踪中知道该类和方法,并且我知道它失败了(因为我有一个异常)。 这让我开始考虑将什么消息放入异常消息中。首先创建一个异常类,如果不存在,对于一般的原因(例如PropertyNotFoundException-的原因),然后当我把它的消息表示什么地方出了错(如“无法找到财产‘IDontExist’的节点1234 “- 什么)。哪里是StackTrace。该时可以在日志中结束了(如果适用)。该如何是为开发者制定(并修复) 您还有其他引发异常的技巧吗?特别是关于创建新类型和异常消息。
101 exceptions 

12
有人告诉我,异常仅应在例外情况下使用。我怎么知道我的案子是否特殊?
我在这里的特定情况是用户可以将字符串传递到应用程序中,应用程序将对其进行解析并将其分配给结构化对象。有时,用户可能输入了无效的内容。例如,他们的输入可能描述一个人,但他们可能说他们的年龄是“苹果”。在这种情况下,正确的行为是回滚事务并告诉用户发生了错误,他们将不得不再次尝试。可能需要报告我们在输入中发现的每个错误,而不仅仅是第一个。 在这种情况下,我认为我们应该抛出异常。他不同意,说:“例外应该是例外:应该预期用户可能会输入无效数据,所以这不是例外情况”,我真的不知道该如何辩驳,因为按照单词的定义,他似乎是正确的。 但是,据我了解,这就是为什么首先发明例外的原因。过去,您必须检查结果以查看是否发生错误。如果检查失败,可能会在您不注意的情况下发生不良情况。 无一例外,堆栈的每个级别都需要检查调用的方法的结果,如果程序员忘记检入这些级别之一,则代码可能会意外继续并保存无效数据(例如)。这种方式似乎更容易出错。 无论如何,请随时纠正我在这里所说的任何内容。我的主要问题是,如果有人说例外应该是例外,我怎么知道我的情况是否是例外?

9
检查优先与异常处理?
我正在阅读“ Head First Python”一书(这是我今年要学习的语言),然后进入一节,他们讨论了两种代码技术: 检查First与Exception处理。 这是Python代码的示例: # Checking First for eachLine in open("../../data/sketch.txt"): if eachLine.find(":") != -1: (role, lineSpoken) = eachLine.split(":",1) print("role=%(role)s lineSpoken=%(lineSpoken)s" % locals()) # Exception handling for eachLine in open("../../data/sketch.txt"): try: (role, lineSpoken) = eachLine.split(":",1) print("role=%(role)s lineSpoken=%(lineSpoken)s" % locals()) except: pass 第一个示例直接处理.split函数中的问题。第二个只是让异常处理程序处理它(并忽略该问题)。 他们在书中主张使用异常处理而不是先检查。该论点是异常代码将捕获所有错误,其中首先进行检查将仅捕获您所考虑的事情(并且您错过了极端情况)。我被教导首先要检查,所以我的本能是这样做,但是他们的想法很有趣。我从未想过使用异常处理来处理案例。 通常认为这两种方法中的哪一种更好?


8
返回魔术值,引发异常或在失败时返回false?
有时我最终不得不为类库编写方法或属性,对于该类库,没有真正的答案不是偶然,而是失败。无法确定,无法使用,无法找到,当前无法执行或没有其他可用数据。 我认为对于这种相对非异常的情况,有三种可能的解决方案可以指示C#4失败: 返回一个没有其他含义的魔术值(例如null和-1); 抛出异常(例如KeyNotFoundException); return false并在out参数中提供实际的返回值(例如Dictionary<,>.TryGetValue)。 所以问题是:我应该在哪种非例外情况下抛出异常?而且,如果我不应该抛出:什么时候返回在实现Try*带有out参数的方法时产生的魔术值?(对我来说,该out参数似乎很脏,要正确使用该参数还需要更多工作。) 我正在寻找实际的答案,例如涉及设计准则的答案(我对Try*方法一无所知),可用性(因为我向类库提出的要求),与BCL的一致性以及可读性。 在.NET Framework基类库中,使用了所有三种方法: 返回一个没有其他含义的魔术值: Collection<T>.IndexOf 返回-1, StreamReader.Read 返回-1, Math.Sqrt 返回NaN, Hashtable.Item 返回null; 抛出异常: Dictionary<,>.Item 抛出KeyNotFoundException, Double.Parse抛出FormatException; 要么 return false并在out参数中提供实际的返回值: Dictionary<,>.TryGetValue, Double.TryParse。 请注意,正如HashtableC#中没有泛型时创建的那样,它使用object,因此可以null作为魔术值返回。但是对于泛型,在中使用了例外Dictionary<,>,而最初没有TryGetValue。见解显然在改变。 显然,Item- TryGetValue和Parse- TryParse偶是有原因的,所以我认为抛出异常的非特殊的故障是在C#4 没有这样做。但是,Try*即使存在,方法也不总是存在Dictionary<,>.Item。

10
异常,错误代码和有区别的联合
我最近开始了C#编程工作,但是我在Haskell有很多背景。 但是我知道C#是一种面向对象的语言,我不想将圆钉插入方孔中。 我阅读了Microsoft的Exception Throwing文章,其中指出: 不要返回错误代码。 但是习惯了Haskell,我一直在使用C#数据类型OneOf,将结果作为“正确”值返回,或者将错误(通常是Enumeration)作为“左侧”值返回。 这很像EitherHaskell中的约定。 在我看来,这比例外情况更安全。在C#中,忽略异常不会产生编译错误,如果未捕获到异常,它们只会冒泡并使程序崩溃。这也许比忽略错误代码并产生不确定的行为要好,但是崩溃客户的软件仍然不是一件好事,尤其是当它在后台执行许多其他重要的业务任务时。 使用时OneOf,必须非常明确地解压缩它并处理返回值和错误代码。而且,如果在调用堆栈的那个阶段不知道如何处理它,则需要将其放入当前函数的返回值中,以便调用者知道可能会导致错误。 但这似乎不是微软建议的方法。 使用OneOf代替异常来处理“普通”异常(例如“找不到文件”等)是一种合理的方法还是一种可怕的做法? 值得注意的是,我听说过异常作为控制流被认为是一种严重的反模式,因此,如果“异常”是您通常会在不结束程序的情况下处理的,那么“控制流”是否就某种方式而言呢?我了解这里有些灰色区域。 注意,我不使用OneOf“内存不足”之类的东西,但我不希望从中恢复的条件仍然会引发异常。但是我觉得这是非常合理的问题,例如未解析的用户输入本质上是“控制流”,并且可能不应引发异常。 随后的想法: 从这次讨论中,我目前要讲的内容如下: 如果您希望直接调用者catch在大多数时间都可以处理异常并继续其工作(也许通过另一条路径),则它可能应该是返回类型的一部分。Optional或OneOf在这里有用。 如果您希望直接调用方在大多数情况下不会捕获异常,请抛出异常,以免手动将异常传递到堆栈中。 如果您不确定直接呼叫者将要做什么,则可以同时提供Parse和和TryParse。
80 c#  exceptions 

8
为什么使用try…最终没有catch子句?
经典的编程方式是使用try ... catch。什么时候适合使用try不catch? 在Python中,以下内容看起来合法且有意义: try: #do work finally: #do something unconditional 但是,代码没有catch任何内容。类似地,在Java中可能会认为如下: try { //for example try to get a database connection } finally { //closeConnection(connection) } 看起来不错,突然间我不必担心异常类型等。如果这是一种好的做法,那么什么时候才是好的做法?另外,为什么这不是良好做法或不合法?(我没有编译源代码。我正在询问它,因为它可能是Java的语法错误。我检查了Python是否确实可以编译。) 我遇到的一个相关问题是:我继续编写函数/方法,最后必须返回一些内容。但是,它可能位于不应该到达的地方,必须是返回点。因此,即使我处理了上面的异常,我仍会NULL在代码中某些不应该到达的位置(通常是方法/函数的结尾)返回或返回一个空字符串。我一直设法对代码进行重组,以使它不必一定要进行重组return NULL,因为这看起来绝对不像是一种好习惯。

14
为什么忽略算术溢出?
曾经尝试用您喜欢的编程语言对1到2,000,000之间的所有数字求和吗?结果很容易手动计算:2,000,001,000,000,比无符号32位整数的最大值大900倍。 C#打印出来-1453759936-负值!而且我猜Java也是如此。 这意味着有一些通用的编程语言默认情况下会忽略算术溢出(在C#中,存在用于更改该值的隐藏选项)。在我看来,这是一种非常冒险的行为,难道不是由这样的溢出导致Ariane 5崩溃吗? 那么:如此危险的行为背后的设计决策是什么? 编辑: 这个问题的第一个答案表示检查的过度成本。让我们执行一个简短的C#程序来测试此假设: Stopwatch watch = Stopwatch.StartNew(); checked { for (int i = 0; i < 200000; i++) { int sum = 0; for (int j = 1; j < 50000; j++) { sum += j; } } } watch.Stop(); Console.WriteLine(watch.Elapsed.TotalMilliseconds); 在我的计算机上,选中的版本需要11015毫秒,而未选中的版本需要4125毫秒。即检查步骤几乎花了两倍的时间(总共是原始时间的三倍)。但是,有了10,000,000,000次重复,检查所花费的时间仍不到1纳秒。在某些情况下,这很重要,但是对于大多数应用程序而言,这并不重要。 编辑2: 我使用/p:CheckForOverflowUnderflow="false"参数(通常,我打开了溢出检查功能)重新编译了服务器应用程序(Windows服务,该服务分析从多个传感器接收的数据,涉及很多数字运算),并将其部署在设备上。Nagios监控显示,平均CPU负载保持在17%。 这意味着在上面的虚构示例中发现的性能下降与我们的应用完全无关。


12
有一个标志来指示是否应该抛出错误
我最近开始在一个与一些年龄较大的开发人员(大约50岁以上)一起工作的地方。他们致力于处理无法解决系统故障的航空关键应用。结果,较老的程序员倾向于以这种方式进行编码。 他倾向于在对象中放入一个布尔值,以指示是否应该引发异常。 例 public class AreaCalculator { AreaCalculator(bool shouldThrowExceptions) { ... } CalculateArea(int x, int y) { if(x < 0 || y < 0) { if(shouldThrowExceptions) throwException; else return 0; } } } (在我们的项目中,该方法可能会失败,因为我们正在尝试使用当时无法使用的网络设备。区域示例仅是异常标志的示例) 对我来说,这似乎是一种代码气味。编写单元测试变得有些复杂,因为每次都必须测试异常标志。另外,如果出现问题,您是否想立即知道?确定如何继续是呼叫者的责任吗? 他的逻辑/理由是我们的程序需要做一件事,向用户显示数据。任何其他不会阻止我们这样做的异常都应忽略。我同意不应忽视它们,而应该冒泡并由适当的人员来处理,而不必为此处理标志。 这是处理异常的好方法吗? 编辑:只是为了提供更多有关设计决策的信息,我怀疑这是因为如果该组件失败,程序仍可以运行并完成其主要任务。因此,当用户可以正常工作时,我们不想抛出异常(不处理它?)并让它删除程序。 编辑2:为了提供更多上下文,在本例中,该方法被调用来重置网卡。当网卡断开连接并重新连接时,会出现问题,它被分配了另一个IP地址,因此Reset将引发异常,因为我们将尝试使用旧的IP重置硬件。

15
可以使用空的catch语句吗?
我考虑了一下,无法提出一个例子。为什么有人要捕获异常却什么也不做呢?能给我举个例子吗?也许这只是不应该做的事情。
58 exceptions 

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.