我有一些代码,当它执行时,它会抛出NullReferenceException,说:
对象引用未设置为对象的实例。
这意味着什么,我可以做什么来修复这个错误?
我有一些代码,当它执行时,它会抛出NullReferenceException,说:
对象引用未设置为对象的实例。
这意味着什么,我可以做什么来修复这个错误?
当前回答
虽然导致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)异常
其他回答
这意味着您的代码使用了一个设置为null的对象引用变量(即它没有引用实际的对象实例)。
为了防止出现错误,应该在使用可能为空的对象之前测试其是否为空。
if (myvar != null)
{
// Go ahead and use myvar
myvar.property = ...
}
else
{
// Whoops! myvar is null and cannot be used without first
// assigning it to an instance reference
// Attempting to use myvar here will result in NullReferenceException
}
简单来说:
您正在尝试访问未创建或当前不在内存中的对象。
那么如何解决这个问题:
调试并让调试器中断。。。它将直接将您带到被破坏的变量。。。现在你的任务是简单地解决这个问题。。在适当的位置使用新关键字。如果这是由于对象不存在而在某些数据库命令上导致的,那么您需要做的就是执行空检查并处理它:如果(i==空){//处理这个}最难的。。如果GC已经收集了对象。。。如果您试图使用字符串查找对象,通常会发生这种情况。。。也就是说,通过对象的名称查找它,那么GC可能已经清理了它。。。这很难找到,会成为一个很大的问题。。。解决这一问题的更好方法是在开发过程中,在必要时进行空检查。这将为您节省大量时间。
通过名称查找,我的意思是某些框架允许您使用字符串查找对象,代码可能如下:FindObject(“ObjectName”);
当您尝试使用的类的对象未实例化时,会发生NullReferenceException或未设置对象实例的Object引用。例如:
假设您有一个名为Student的班级。
public class Student
{
private string FirstName;
private string LastName;
public string GetFullName()
{
return FirstName + LastName;
}
}
现在,考虑另一个你试图检索学生全名的班级。
public class StudentInfo
{
public string GetStudentName()
{
Student s;
string fullname = s.GetFullName();
return fullname;
}
}
如以上代码所示Student s-只声明Student类型的变量,注意Student类此时未实例化。因此,当执行s.GetFullName()语句时,它将抛出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<>实例时使用的特殊规则。