我有一些代码,当它执行时,它会抛出NullReferenceException,说:
对象引用未设置为对象的实例。
这意味着什么,我可以做什么来修复这个错误?
我有一些代码,当它执行时,它会抛出NullReferenceException,说:
对象引用未设置为对象的实例。
这意味着什么,我可以做什么来修复这个错误?
当前回答
更新C#8.02019:可为空的引用类型
C#8.0引入了可为null的引用类型和不可为null引用类型。因此,必须只检查可为null的引用类型,以避免出现NullReferenceException。
如果尚未初始化引用类型,并且希望设置或读取其财产之一,则会抛出NullReferenceException。
例子:
Person p = null;
p.Name = "Harry"; // NullReferenceException occurs here.
您可以通过检查变量是否为空来避免这种情况:
Person p = null;
if (p!=null)
{
p.Name = "Harry"; // Not going to run to this point
}
要完全理解为什么会引发NullReferenceException,必须了解值类型和[引用类型][3]之间的区别。
因此,如果要处理值类型,则不能出现NullReferenceExceptions。尽管在处理引用类型时需要保持警惕!
正如名称所暗示的那样,只有引用类型可以保存引用或直接指向任何对象(或“null”)。而值类型始终包含值。
引用类型(必须选中这些类型):
动态对象一串
值类型(您可以忽略这些类型):
数字类型整数类型浮点类型十进制的布尔用户定义的结构
其他回答
另一种可能发生NullReferenceExceptions的情况是(不正确)使用as运算符:
class Book {
public string Name { get; set; }
}
class Car { }
Car mycar = new Car();
Book mybook = mycar as Book; // Incompatible conversion --> mybook = null
Console.WriteLine(mybook.Name); // NullReferenceException
在这里,Book和Car是不兼容的类型;汽车不能转换成书。当此强制转换失败时,as返回null。在此之后使用mybook会导致NullReferenceException。
通常,应使用强制转换或,如下所示:
如果您希望类型转换总是成功的(即,您知道对象应该是什么),那么应该使用强制转换:
ComicBook cb = (ComicBook)specificBook;
如果您不确定该类型,但希望尝试将其用作特定类型,请将其用作:
ComicBook cb = specificBook as ComicBook;
if (cb != null) {
// ...
}
当实体框架中使用的实体的类名与web表单代码隐藏文件的类名相同时,添加一种情况。
假设您有一个web表单Contact.aspx,其代码尾类为Contact,实体名称为Contact。
然后,当您调用context.SaveChanges()时,以下代码将引发NullReferenceException
Contact contact = new Contact { Name = "Abhinav"};
var context = new DataContext();
context.Contacts.Add(contact);
context.SaveChanges(); // NullReferenceException at this line
为了完整起见,DataContext类
public class DataContext : DbContext
{
public DbSet<Contact> Contacts {get; set;}
}
和Contact实体类。有时实体类是分部类,因此您也可以在其他文件中扩展它们。
public partial class Contact
{
public string Name {get; set;}
}
当实体和代码尾类都在同一命名空间中时,会发生错误。要解决此问题,请重命名Contact.aspx的实体类或codebehind类。
原因我仍然不确定原因。但每当任何实体类将扩展System.Web.UI.Page时,都会发生此错误。
有关讨论,请查看DbContext.saveChanges()中的NullReferenceException
有趣的是,本页的答案中没有一个提到两种边缘情况:
边缘案例#1:对字典的并发访问
.NET中的泛型字典不是线程安全的,当您尝试从两个并发线程访问密钥时,它们有时可能会抛出NullReference,甚至(更频繁)抛出KeyNotFoundException。在这种情况下,这个例外情况很容易引起误解。
边缘案例#2:不安全代码
如果不安全代码引发NullReferenceException,您可以查看指针变量,并检查它们是否存在IntPtr.Zero或其他内容。这是同一回事(“空指针异常”),但在不安全的代码中,变量通常被转换为值类型/数组等,你会把头撞在墙上,想知道值类型如何抛出此异常。
(顺便说一句,除非您需要,否则不使用不安全代码的另一个原因。)
边缘案例3:Visual Studio多监视器设置,辅助监视器的DPI设置与主监视器不同
此边缘案例是特定于软件的,属于Visual Studio 2019 IDE(以及可能更早的版本)。
一种重现问题的方法:将任何组件从工具箱拖到非主监视器上的Windows窗体上,该窗体的DPI设置与主监视器不同,然后会弹出一个“Object reference not set to A instance of A Object”(对象引用未设置为对象的实例)。根据这个线程,这个问题已经知道了很长一段时间,在编写时仍然没有解决。
当我们试图访问空对象的财产时,或者当字符串值变为空并且我们试图访问字符串方法时,会抛出NullReferenceException。
例如:
访问空字符串的字符串方法时:string str=string.Empty;str.ToLower();//抛出空引用异常访问空对象的属性时:公共类人员{公共字符串名称{get;set;}}人员对象人员;objPerson.Name///抛出空引用异常
简单来说:
您正在尝试访问未创建或当前不在内存中的对象。
那么如何解决这个问题:
调试并让调试器中断。。。它将直接将您带到被破坏的变量。。。现在你的任务是简单地解决这个问题。。在适当的位置使用新关键字。如果这是由于对象不存在而在某些数据库命令上导致的,那么您需要做的就是执行空检查并处理它:如果(i==空){//处理这个}最难的。。如果GC已经收集了对象。。。如果您试图使用字符串查找对象,通常会发生这种情况。。。也就是说,通过对象的名称查找它,那么GC可能已经清理了它。。。这很难找到,会成为一个很大的问题。。。解决这一问题的更好方法是在开发过程中,在必要时进行空检查。这将为您节省大量时间。
通过名称查找,我的意思是某些框架允许您使用字符串查找对象,代码可能如下:FindObject(“ObjectName”);