Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中处理NullReferenceException的更好方法#_C#_Exception Handling - Fatal编程技术网

C# 在C中处理NullReferenceException的更好方法#

C# 在C中处理NullReferenceException的更好方法#,c#,exception-handling,C#,Exception Handling,我最近遇到了一个编码错误,在某些情况下变量没有被初始化,我得到了一个NullReferenceException。这花了一段时间进行调试,因为我必须找到将生成此错误的数据位来重新创建错误,因为异常没有给出变量名 显然,我可以在使用前检查每个变量并抛出一个信息异常,但是有更好的方法(读更少的编码)吗?我的另一个想法是附带pdb文件,以便错误信息包含导致错误的代码行。其他人如何避免/处理这个问题 首先,不要在一次陈述中做太多。如果在一行中有大量的解引用操作,那么就很难找到罪魁祸首。这也很有帮助——如

我最近遇到了一个编码错误,在某些情况下变量没有被初始化,我得到了一个
NullReferenceException
。这花了一段时间进行调试,因为我必须找到将生成此错误的数据位来重新创建错误,因为异常没有给出变量名

显然,我可以在使用前检查每个变量并抛出一个信息异常,但是有更好的方法(读更少的编码)吗?我的另一个想法是附带
pdb
文件,以便错误信息包含导致错误的代码行。其他人如何避免/处理这个问题


首先,不要在一次陈述中做太多。如果在一行中有大量的解引用操作,那么就很难找到罪魁祸首。这也很有帮助——如果你有订单、售货员、经理、地址、街道、长度之类的东西,那么当你遇到异常时,你有很多选择。(我对得墨忒尔定律并不武断,但一切都要适度…)

第二:宁愿使用强制转换而不是使用
作为
,除非对象是另一种类型是有效的,这通常会在之后立即进行空检查。因此,这里:

// 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,并最终将其追溯到
text
为null,但您不知道这是因为
foo
为null,还是因为它是一个意外类型。如果它真的应该是一个
字符串
,那么改为强制转换:

string text = (string) foo;
现在,您将能够区分这两种场景之间的差异

第三:正如其他人所说,验证您的数据——通常是针对公共和潜在内部API的参数。我在足够多的地方这样做,因为我有一个实用程序类来帮助我清理支票。例如(来自):


您也应该记录哪些可以为null,哪些不可以为null。

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

这很简单

if( this.SubObject == null )
{
    throw new Exception("Could not perform METHOD - SubObject is null.");
}
else
{
...
}
否则我想不出任何方法来彻底检查。不管怎样,不做这些检查对我来说没有多大意义;我觉得这是一种很好的做法。

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

现在,我知道这是多么痛苦,所以您可以研究为您完成这项工作的程序集重写工具。其思想是,您将拥有一种属性,用于标记那些不能为
null
的参数:

public void Method([NotNull] string name) { ...
重写者会填补空白

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

name.CheckNotNull();

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


是的,交付PDB(即使是发布版本)是获得完整堆栈跟踪的一个好方法,可以精确定位错误的确切位置和原因。但无论您选择什么诊断方法,都需要在应用程序的设计中加入它(理想情况下)。改装现有的应用程序可能会很繁琐,而且需要大量的时间/金钱。

如果您只是想寻找一种更简洁的方法来编写代码,以避免出现空引用,请不要忽略空合并操作符
??


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

总是
Assert
对空值进行大量断言。@leppie-这是很多断言!是的,我可以这么做,但我希望有一个更优雅的解决方案来考虑像我忘记这么做这样的情况:)Protip:让你的方法小一些(比如最多10-20行),那么你就不需要行号了。@leppie:我不同意第二部分。显然,保持方法简短是一个好主意,但即使如此,行号也可以显著缩短调试时间。在设计时通知您这些问题非常好。是的,这些都是很好的提示。我是否应该与pdb文件一起发货,以便给出行?目前,我的生产代码提供了方法名称,但没有提供增加一定难度的行。除了“不要在每一行做太多”之外,您还可以添加“不要在每一个方法中做太多”。这有助于将问题最小化。@directedbit:这取决于您的情况。。。对于服务器端代码,绝对是这样。如果您发送的是客户端代码,那么可能会更加敏感或混乱……这是一个很好的建议。不幸的是,这一个是我的全部。我在函数中放错了一个括号,所以一个变量在它的初始化范围之外被使用。不总是这样。我通常扩展异常。这只是一个例子。在这种情况下,如果状态本身有效,则应使用InvalidOperationException,如果状态无效,则应使用ArgumentNullException来阻止您进入该状态。谢谢,您是否建议使用任何方法将其烘焙。目前,我有一种简单的方法,可以对任何未处理的异常记录尽可能多的细节。。。有时,您需要关于发生了什么的特定信息,因为您可能预期会出现某些类型的错误。在其他情况下,就像我说的,你可能只是遇到了意想不到的情况。您可以做的第一件事是钩住
AppDomain.UnhandledException
(或web应用程序的global.asax中的
Application\u Error
),然后根据需要开始改装各个方法。
name.CheckNotNull();