我有一些代码,当它执行时,它会抛出NullReferenceException,说:
对象引用未设置为对象的实例。
这意味着什么,我可以做什么来修复这个错误?
我有一些代码,当它执行时,它会抛出NullReferenceException,说:
对象引用未设置为对象的实例。
这意味着什么,我可以做什么来修复这个错误?
当前回答
抛出此异常的一个示例是:当您试图检查某个对象时,该对象为空。
例如:
string testString = null; //Because it doesn't have a value (i.e. it's null; "Length" cannot do what it needs to do)
if (testString.Length == 0) // Throws a nullreferenceexception
{
//Do something
}
当您尝试对尚未实例化的对象(即上面的代码)执行操作时,.NET运行时将抛出NullReferenceException。
与ArgumentNullException相比,ArgumentNullException通常在方法期望传递给它的内容不为null时作为防御措施抛出。
更多信息请参见C#NullReferenceException和Null参数。
其他回答
Simon Mourier举了一个例子:
object o = null;
DateTime d = (DateTime)o; // NullReferenceException
其中,从对象(或从System.ValueType或System.Enum类之一,或从接口类型)到值类型(非Nullable<>)的拆箱转换(强制转换)本身会产生NullReferenceException。
在另一个方向上,从HasValue等于false的Nullable<>到引用类型的装箱转换可能会给出一个空引用,然后会导致NullReferenceException。典型的例子是:
DateTime? d = null;
var s = d.ToString(); // OK, no exception (no boxing), returns ""
var t = d.GetType(); // Bang! d is boxed, NullReferenceException
有时拳击会以另一种方式进行。例如,对于此非泛型扩展方法:
public static void MyExtension(this object x)
{
x.ToString();
}
以下代码将是有问题的:
DateTime? d = null;
d.MyExtension(); // Leads to boxing, NullReferenceException occurs inside the body of the called method, not here.
出现这些情况是因为运行时在装箱Nullable<>实例时使用的特殊规则。
实际上,修复NullReferenceExeption的最简单方法有两种。
例如,如果你有一个附带脚本的GameObject和一个名为rb(rigidbody)的变量,那么当你开始游戏时,这个变量将以null开头。这就是为什么会得到NullReferenceExeption,因为计算机中没有存储在该变量中的数据。
我将使用刚体变量作为示例。实际上,我们可以通过以下几种方式轻松地添加数据:
使用AddComponent>Physics>RigidBody将刚体添加到对象然后进入脚本并键入rb=GetComponent<Rigidbody>();这行代码在Start()或Awake()函数下最有效。您可以通过编程方式添加一个组件,同时用一行代码分配变量:rb=AddComponent<RigidBody>();
进一步注意:如果您希望Unity向您的对象添加组件,而您可能忘记添加组件,那么可以在类声明上方键入[RequireComponent(typeof(RigidBody))](所有using下方的空格)。
享受并享受制作游戏的乐趣!
当我们试图访问空对象的财产时,或者当字符串值变为空并且我们试图访问字符串方法时,会抛出NullReferenceException。
例如:
访问空字符串的字符串方法时:string str=string.Empty;str.ToLower();//抛出空引用异常访问空对象的属性时:公共类人员{公共字符串名称{get;set;}}人员对象人员;objPerson.Name///抛出空引用异常
虽然导致NullReferenceExceptions的原因和避免/修复此类异常的方法已经在其他答案中得到了解决,但许多程序员尚未学会的是如何在开发过程中独立调试此类异常。
在Visual Studio中,由于Visual Studio调试器,这通常很容易。
首先,确保将捕获正确的错误-请参见如何允许在VS2010中的“System.NullReferenceException”上中断?注释1
然后从调试开始(F5)或将[VS调试器]附加到正在运行的进程。有时,使用Debugger.Break可能很有用,它将提示启动调试器。
现在,当抛出(或未处理)NullReferenceException时,调试器将在发生异常的行上停止(记住上面设置的规则吗?)。有时错误很容易被发现。
例如,在下一行中,唯一可能导致异常的代码是myString求值为null。这可以通过查看观察窗口或在即时窗口中运行表达式来验证。
var x = myString.Trim();
在更高级的情况下,例如以下情况,您需要使用上述技术之一(观察或即时窗口)来检查表达式,以确定str1是否为null或str2是否为null。
var x = str1.Trim() + str2.Trim();
一旦找到了抛出异常的位置,通常很难反向推理,以找出空值被[错误]引入的位置--
花时间了解异常原因。检查空表达式。检查之前可能导致此类空表达式的表达式。根据需要添加断点并单步执行程序。使用调试器。
1如果“抛出时中断”过于激进,并且调试器在.NET或第三方库中的NPE上停止,则可以使用“用户未处理时中断”来限制捕获的异常。此外,VS2012还引入了Just My Code,我建议您也启用它。
如果您在启用“仅我的代码”的情况下进行调试,则行为略有不同。如果启用了“仅我的代码”,调试器将忽略在“我的代码外引发的、不通过“我的码”的第一次公共语言运行时(CLR)异常
请注意,无论情况如何,.NET中的原因总是相同的:
您正在尝试使用值为Nothing/null的引用变量。当引用变量的值为Nothing/null时,这意味着它实际上没有保存对堆上存在的任何对象实例的引用。您要么从未向变量赋值,要么从未创建分配给变量的值的实例,要么手动将变量设置为Nothing/null,要么为您调用了将变量设置成Nothing/nnull的函数。