当前位置: 首页 > 知识库问答 >
问题:

在C中正确处理异常和日志#

鲁浩渺
2023-03-14

假设我有一个类Person,具有不同数据类型的不同属性,我在我的主方法中有这样的代码:

Person p1 = new Person
    {
        Name = inputName,
        DateOfBirth = inputDOB,
        Height = height,
        Weight = weight,
        Passport = inputPassport
    };

现在,假设高度的赋值引发了一个异常,例如InvalidCastException,代码将停止执行,并且可能会记录一些东西,以防我有一个记录表。问题是,从日志中,我无法确切地理解哪一行和赋值抛出了异常。

是否有任何方法可以捕获异常,并能够记录(数据库中的某个位置)哪个赋值引发异常,以及在这种情况下针对哪种类型的强制转换(例如double to DateTime)。

更新:最后,我通过以下操作解决了我的问题:

  1. 更新代码,使其首先创建对象(不设置属性),然后一次设置一行属性

共有1个答案

单于高逸
2023-03-14

这是一个众所周知的问题。以下是一些与之相关的链接:

  • 无法识别在C#中使用对象初始值设定项时引发异常的属性。
  • 使用对象初始值设定项有什么好处吗

我还使用C#7.3(.net4.7.2)C#8(.netcore3.1)测试了您的场景,问题仍然存在。因此,如果使用对象初始值设定项且其中一个初始值设定项值引发异常,则无法从堆栈跟踪中知道哪个初始值设定项值导致异常。

变通办法

让我们考虑下一节<代码>人>代码>

class Person
{
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    public int Age { get; set; }
}

并假设使用下一个代码创建了类Person的实例:

// Return type of the methods getName(), getDateOfBirth() and getAge() is object.
// Each of this methods can return invalid value, for example, method getAge()
// can return string value causing InvalidCastException.
Person p = new Person
{
    Name = (string) getName(),
    DateOfBirth = (DateTime) getDateOfBirth(),
    Age = (int) getAge()
};

如果一个初始值设定值(例如,将方法getName()的结果强制转换为string数据类型)引发异常,我们将无法知道哪个初始值设定值是异常的原因,因为堆栈跟踪中的行号将指向行Person p=new Person

为了解决这个问题,我们可以拒绝使用对象初始化器,而使用旧样式的对象初始化:

Person p = new Person();
p.Name = (string) getName();
p.DateOfBirth = (DateTime) getDateOfBirth();
p.Age = (int) getAge();

现在,如果发生异常,我们将能够知道发生异常的确切行号。

在这里,我们必须在可读性(对象初始化器)和在初始化期间获得关于异常原因的更准确信息的能力之间进行选择。

还有其他解决办法。例如,我们可以在对象初始值设定项中使用初始值设定项值之前检查它们:

结论

这是一个众所周知的问题。它仍然存在,尚未修复。我们可以通过拒绝使用对象初始值设定项和使用属性设定项(p.Name=(string)getName())来解决这个问题。还可以使用另一种解决方法(例如,在使用对象初始值设定项之前检查初始值设定项值)。

我们应该小心地使用对象初始值设定项。如果初始化值可以抛出异常,我们应该考虑使用属性设置器初始化对象(<html" target="_blank">代码> PNEX=(String)GETNAMEL()/代码>),因为它将来会简化调试。

 类似资料:
  • 我想知道,当我试图在数据库中创建并持久化对象时,处理异常的最佳方法。 因此,我有一个名为Rule的表,其中包含getter和setter: 我有一个方法create谁在数据库中添加对象: 我应该为每个异常使用多个catch吗?谁的方法可以抛出try块 如果我的解决方案是处理异常的好方法,那么如何才能以好的方式打印与异常相关的特定消息 如何在JUnit5中为块的内容引发异常,以测试是否引发了异常(我

  • 问题内容: 我一直在概念上为我的项目决定异常处理结构。 假设您有一个示例: 还有两个子类FileData和StaticData,它们从某些指定的文件中读取数据,StaticData仅返回一些预定义的常量数据。 现在,在读取文件时,可能会在FileData中引发IOException,但是StaticData将永远不会抛出。大多数样式指南建议在调用堆栈上传播Exception,直到有足够的上下文可以

  • 1.【强制】不要捕获Java类库中定义的继承自RuntimeException的运行时异常类,如:IndexOutOfBoundsException / NullPointerException,这类异常由程序员预检查来规避,保证程序健壮性。 正例:if(obj != null) {...} 反例:try { obj.method() } catch(NullPointerException e)

  • 主要内容:try/catch语句,C#中的异常类,自定义异常类,抛出异常在 C# 中,异常是在程序运行出错时引发的,例如以一个数字除以零,所有异常都派生自 System.Exception 类。异常处理则是处理运行时错误的过程,使用异常处理可以使程序在发生错误时保持正常运行。 C# 中的异常处理基于四个关键字构建,分别是 try、catch、finally 和 throw。 try:try 语句块中通常用来存放容易出现异常的代码,其后面紧跟一个或多个 catch 语句

  • 异常是程序在执行期间产生的问题。C++ 异常是指在程序运行时发生的特殊情况,比如尝试除以零的操作。 异常提供了一种转移程序控制权的方式。C++ 异常处理涉及到三个关键字:try、catch、throw。 throw: 当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的。 catch: 在您想要处理问题的地方,通过异常处理程序捕获异常。catch 关键字用于捕获异常。 try

  • 本文向大家介绍Java中断异常的正确处理方法,包括了Java中断异常的正确处理方法的使用技巧和注意事项,需要的朋友参考一下 处理InterruptedException 这个故事可能很熟悉:你正在写一个测试程序,你需要暂停某个线程一段时间,所以你调用 Thread.sleep()。然后编译器或 IDE 就会抱怨说 InterruptedException 没有抛出声明或捕获。什么是 Interru