5

I recently had a coding bug where under certain conditions a variable wasn't being initialized and I was getting a NullReferenceException . This took a while to debug as I had to find the bits of data that would generate this to recreate it the error as the exception doesn't give the variable name.

Obviously I could check every variable before use and throw an informative exception but is there a better (read less coding) way of doing this? Another thought I had was shipping with the pdb files so that the error information would contain the code line that caused the error. How do other people avoid / handle this problem?

Thanks

4

5 回答 5

11

首先:不要在一个语句中做太多。如果您在一行中有大量的取消引用操作,那么找到罪魁祸首将变得更加困难墨忒耳法则对此也有帮助——如果你有类似order.SalesClerk.Manager.Address.Street.Length的情况,那么当你遇到异常时,你有很多选择可以涉足。(我对得墨忒耳法则并不教条,但一切都要适度……)

其次:更喜欢强制转换 using as,除非对象是不同的类型是有效的,这通常会在之后立即进行空检查。所以在这里:

// What if foo is actually a Control, but we expect it to be String?
string text = foo as string;
// Several lines later
int length = text.Length; // Bang!

在这里,我们会得到一个 NullReferenceException 并最终将其追溯到textnull ——但是您将不知道这foo是因为它是 null 还是因为它是一个意外的类型。如果它真的应该是 a string,则改为:

string text = (string) foo;

现在您将能够区分这两种情况。

第三:正如其他人所说,验证您的数据 - 通常是公共和潜在内部 API 的参数。我在Noda Time的足够多的地方这样做,我有一个实用程序类来帮助我整理检查。例如(来自Period):

internal LocalInstant AddTo(LocalInstant localInstant,
                            CalendarSystem calendar, int scalar)
{
    Preconditions.CheckNotNull(calendar, "calendar");
    ...
}

您也应该记录什么可以和不可以为空。

于 2012-04-12T16:57:51.557 回答
3

在很多情况下,几乎不可能计划和解释可能在应用程序执行流程中的任何给定点发生的每种类型的异常。防御性编码仅在某一点上有效。诀窍是将可靠的诊断堆栈整合到您的应用程序中,它可以为您提供有关未处理错误和崩溃的有意义的信息。在应用程序域级别拥有一个好的顶级(最后一搏)处理程序将对此有很大帮助。

是的,发布 PDB(即使是发布版本)是获得完整堆栈跟踪的好方法,可以查明错误的确切位置和原因。但是,无论您选择何种诊断方法,都需要从一开始就将其融入应用程序的设计中(理想情况下)。改造现有的应用程序可能是乏味的,而且是时间/金钱密集型的。

于 2012-04-12T17:00:13.737 回答
2

很抱歉,我将始终进行检查以验证我在特定方法中使用的任何对象都不为空。

这很简单

if( this.SubObject == null )
{
    throw new Exception("Could not perform METHOD - SubObject is null.");
}
else
{
...
}

否则我想不出任何彻底的方法。无论如何不进行这些检查对我来说没有多大意义;我觉得这只是一种很好的做法。

于 2012-04-12T16:58:27.390 回答
2

首先,您应该始终验证您的输入。如果null不允许,则抛出ArgumentNullException.

现在,我知道这有多痛苦,因此您可以研究为您完成此操作的程序集重写工具。这个想法是你会有一种属性来标记那些不能是的参数null

public void Method([NotNull] string name) { ...

重写者将填补空白......

或者一个简单的扩展方法可以使它更容易

name.CheckNotNull();
于 2012-04-12T17:00:12.970 回答
2

如果您只是在寻找一种更紧凑的方式来针对具有空引用进行编码,请不要忽视空合并运算符?? MSDN

显然,这取决于你在做什么,但它可以用来避免额外的 if 语句。

于 2012-04-12T17:18:22.770 回答