是否有可能在Dynamics AX中捕获“未初始化的对象”异常?

时间:2013-01-23 23:57:59

标签: dynamics-ax-2009 x++ axapta

问题:

我有一些代码失败,因为对象尚未初始化。检测到此错误的解决方案很容易修复。然而,让我感到惊讶的是,我精心设计的异常处理并未捕获此异常。这意味着未记录或处理异常,并且从未执行try catch块之后的代码。 try ... catch块在交易之外,因此没有问题。

在这种特殊情况下,异常是在批处理(RunBaseBatch)作业中。该工作处理了几个不相关的处理任务。一旦满足异常条件,作业就会终止,因此从不调用其他不相关的处理任务。

有没有人知道是否有可能在Dynamics AX 2009中捕获“未初始化的对象”异常?我读了一篇帖子说可能无法捕获AX中的某些异常,但是,我希望情况并非如此(参考:https://community.dynamics.com/product/ax/f/33/p/16352/23700.aspx#23700)。

代码示例: 这是一些简化的代码,可以重现这个问题:

server static void main(Args args)
{
    Array   arr;
    ;
    info ("debug: before try...catch");
    try
    {
//        ttsbegin;       // enable/disable to test with transactions
//        arr = new Array(Types::String);     // Enabling this line will prevent the exception
          arr.exists(3);
//        ttscommit;      // enable/disable to test with transactions
    }
    catch (Exception::Internal)  // This exception handler was the Magic Sauce!!
    {
        info ("debug: catch (Exception::Internal)");
    }
    catch (Exception::Error)
    {
        info ("debug: catch (Exception::Error)");
    }
    catch
    {
        info ("debug: catch");
    }
    info ("debug: after try...catch");
}

更新2013-01-29 我等着接受答案,直到这个问题被更多地看待。谢谢你到目前为止的答案。

我知道我给出的例子很简单。这种类型的bug在知道时很容易修复。防御性编程总是一个好主意。

然而,在现实世界中,发生错误的代码非常复杂。错误发生在子类的重载方法的几个深层。它发生在特定场景中,当重载方法损坏了超类中成员变量的受保护值时。这就是代码中发生错误的地方,但是,在超级类再次尝试使用成员变量之前,它并没有表现出来。当检测到并追踪该错误时,该错误被立即修复。

防守,是的,每次使用它都可以检查每个受保护的成员变量,但这确实会影响性能,代码可读性,实用性等,这就是语言提供异常处理的原因。

这里的问题是如何捕获这些类型的错误以使代码更健壮和防弹?在大多数开发环境(例如C,C ++,C#或Java)中,可以使用顶级的try ... catch来捕获,记录和清理所有意外异常。因此代码将能够继续处理其他不相关的任务。 AX正在某种程度上继续,因为当这个错误发生时,整个系统不会停止。但是,由于AX / X ++中存在缺陷,因此此作业中的catch之后的代码未执行。

我正在寻找一种创新的解决方案或解决方案(如果存在),以捕获“未初始化的对象”异常(实际上是所有异常)并继续处理。

3 个答案:

答案 0 :(得分:2)

你不能在传统意义上“抓住”它,但你可以避免它发生。在运行任何对象之前,只需测试对象是否存在:

if(object)
{
    // Exists; Execute statements with object here
}
else 
{
    // Doesn't exist
}

这是有效的,因为如果未初始化对象,则将其转换为null。 (Null == 0)== false

如果初始化对象,它将具有除null之外的某些值。 (!Null!= 0)== true

希望有所帮助!

答案 1 :(得分:1)

详细说明,如您链接到的帖子中所述,无法捕获Object Not Initialized错误。但是,您可以在尝试针对您无法控制的变量运行函数之前添加一个简单的检查来“修复”代码(例如,如果您要求将Array类型作为函数的参数,并且您希望函数为从班级外面打电话。)

    try
    {
          if (arr)
              arr.exists(3);
    }

如果对象尚未实例化,则if(arr)语句足以跳过处理,从而有效地绕过错误。但是,这显然不会将错误进一步推向链。如果你真的想要,你可以让它抛出一个可以被捕获的不同错误,但显然这不太理想。

在这种情况下,由于RunBaseBatch类可能不是您想要修改的东西,因此最好确保在调用问题方法之前正确定义导致问题的对象,并在测试中发现这些错误。

答案 2 :(得分:1)

你可以,但你不应该。这样的行为几乎肯定是代码的糟糕设计,不可避免地将来会遇到更多问题。

您需要将代码防御设置为此案例,确保在使用之前对对象进行实例化。否则,您将catch代码用于预期的行为,这没有任何意义。

编辑2013/02/18

在您所描述的复杂场景中,通常很难完全控制解决方案。在AX中,try..catch语句非常简单,并且在很多情况下都不是真正需要的(不像Java,C#,......总是建议使用)。

这种简化在几乎所有AX开发的情况下都很好,因为您不需要在异常处理上浪费时间。只要让他们加注,InfoLog就会以简单可靠的方式处理它们。

当你真的需要这种控制时,最大的问题就出现了...当它没有真正的强制方式时。我不确定这是否真的是一个标准问题,或者产品团队是否会以这种方式工作,但这种情况总是给AX带来麻烦。当你需要捕捉一些特定的问题时,你必须非常有创意,并且要防止异常,因为抓住它会变得更有创意......

希望这会有所帮助:)