我有一些代码,当它执行时,它会抛出NullReferenceException,说:
对象引用未设置为对象的实例。
这意味着什么,我可以做什么来修复这个错误?
我有一些代码,当它执行时,它会抛出NullReferenceException,说:
对象引用未设置为对象的实例。
这意味着什么,我可以做什么来修复这个错误?
当前回答
当实体框架中使用的实体的类名与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
其他回答
更新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”)。而值类型始终包含值。
引用类型(必须选中这些类型):
动态对象一串
值类型(您可以忽略这些类型):
数字类型整数类型浮点类型十进制的布尔用户定义的结构
关于“我该怎么办”的问题,可以有很多答案。
在开发时防止这种错误情况的一种更“正式”的方法是在代码中应用契约设计。这意味着在开发时,需要在系统上设置类不变量,和/或甚至函数/方法前置条件和后置条件。
简而言之,类不变量确保类中有一些约束在正常使用中不会被违反(因此,类不会处于不一致的状态)。前置条件意味着作为函数/方法输入的数据必须遵循某些约束集,并且永远不会违反这些约束,后置条件意味着函数/方法输出必须再次遵循这些约束集,而永远不会违反它们。在执行无错误程序期间,不应违反合同条件,因此,在调试模式下实际检查合同设计,而在发布版本中禁用,以最大化开发的系统性能。
通过这种方式,可以避免由于违反约束集而导致的NullReferenceException情况。例如,如果在类中使用对象属性X,然后尝试调用其方法之一,并且X具有空值,则这将导致NullReferenceException:
public X { get; set; }
public void InvokeX()
{
X.DoSomething(); // if X value is null, you will get a NullReferenceException
}
但是,如果您将“属性X永远不能有空值”设置为方法前提条件,则可以防止前面描述的情况:
//Using code contracts:
[ContractInvariantMethod]
protected void ObjectInvariant()
{
Contract.Invariant(X != null);
//...
}
因此,.NET应用程序存在代码合同项目。
或者,可以使用断言应用契约设计。
更新:值得一提的是,这个词是Bertrand Meyer在设计Eiffel编程语言时创造的。
抛出此异常的一个示例是:当您试图检查某个对象时,该对象为空。
例如:
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参数。
错误行“Object reference not set to an instance of a Object.”表示您尚未将实例对象分配给对象引用,但仍在访问该对象的财产/方法。
例如:假设您有一个名为myClass的类,它包含一个属性prop1。
public Class myClass
{
public int prop1 {get;set;}
}
现在,您正在访问其他类中的prop1,如下所示:
public class Demo
{
public void testMethod()
{
myClass ref = null;
ref.prop1 = 1; // This line throws an error
}
}
上述行引发错误,因为类myClass的引用已声明,但未实例化,或者对象的实例未分配给该类的引用。
要解决这个问题,必须实例化(将对象分配给该类的引用)。
public class Demo
{
public void testMethod()
{
myClass ref = null;
ref = new myClass();
ref.prop1 = 1;
}
}
如果在保存或编译构建过程中收到此消息,只需关闭所有文件,然后打开任何文件进行编译和保存即可。
对我来说,原因是我重命名了文件,而旧文件仍然打开。