资讯专栏INFORMATION COLUMN

.NET[C#]中NullReferenceException(未将对象引用到实例)是什么问题?如何

shenhualong / 1864人阅读

摘要:问题分析中的开发中,如果遇到或者未将对象引用到实例这样的提示,那么是你的程序代码正在试图访问一个的引用类型的实体而抛出的异常。

问题分析

C#中的开发中,如果遇到“NullReferenceException”或者“未将对象引用到实例”这样的提示,那么是你的程序代码正在试图访问一个null的引用类型的实体而抛出的异常。可能的原因有:

情景一 未实例化引用类型实体

忘记了实例化一个引用类型。 在下面的示例中,names声明,但决不实例化:

using System;
using System.Collections.Generic;

public class Example
{
   public static void Main(string[] args)
   {
      int value = Int32.Parse(args[0]);
      List names;
      names.Add("Major Major Major");       
   }
}

此例中的 names在使用之前并没有初始化,修复后的:

using System;
using System.Collections.Generic;

public class Example
{
   public static void Main()
   {
      List names = new List();
      names.Add("Major Major Major");
   }
}
情景二 泛型连写

如下代码:

ref1.ref2.ref3.member    

如果ref1 或者 ref2 或者 ref3任意一个为空时,此代码均会抛出NullReferenceException(未将对象引用到实例)的异常错误。我们可以重写这个表达式来检查以下的r1,r2,r3是否为null:

var r1 = ref1;    
var r2 = r1.ref2;
var r3 = r2.ref3;
r3.member
情景三 类的实例未初始化

如下代码:

public class Book {
    public string Title { get; set; }
}
public class Example {
    public void Foo() {
        Book b1;
        string title = b1.Title; 
    }
}

其中,Example类中的b1并未实例化,会抛出NullReferenceException(未将对象引用到实例)异常,解决方法:

使用new关键字来实例化b1对象

修复后的代码:

public class Book {
    public string Title { get; set; }
}
public class Example {
    public void Foo() {
        Book b1 = new Book();
        string title = b1.Title;
    }
}
情景四 间接引用

如下代码:

public class Person {
    public int Age { get; set; }
}
public class Book {
    public Person Author { get; set; }
}
public class Example {
    public void Foo() {
        Book b1 = new Book();
        int authorAge = b1.Author.Age; 
    }
}

这里的 Example 类中的b1已被实例化,但如果我们运行程序,依然会抛出NullReferenceException(未将对象引用到实例)异常。是因为 Book 类中包含了另外一个引用类 Person 但并没有被实例化,解决方式可以在Book的构造器中直接实例化,如:

public class Person {
    public int Age { get; set; }
}
public class Book {
    public Book(){
        Author = new Person();
    }
    public Person Author { get; set; }
}
public class Example {
    public void Foo() {
        Book b1 = new Book();
        int authorAge = b1.Author.Age; 
    }
}

当然,你也可以在使用 Book 这个类的实例时再来初始化 Person 这个引用类,如下:

public class Person {
    public int Age { get; set; }
}
public class Book {
    public Person Author { get; set; }
}
public class Example {
    public void Foo() {
        Book b1 = new Book();
        b1.Author = new Person();
        int authorAge = b1.Author.Age; 
    }
}
情景五 数组为null
int[] numbers = null;
int n = numbers[0]; 
Person[] people = new Person[5];
people[0].Age = 20
long[][] array = new long[1][];
array[0][0] = 3;

这三种数组的定义均为null,抛出NullReferenceException(未将对象引用到实例)的异常

情景六 数据字典为null
Dictionary agesForNames = null;
int age = agesForNames["Bob"];

这里的 agesForNames字典为 null,抛出NullReferenceException(未将对象引用到实例)的异常,使用new关键字来初始化:

Dictionary agesForNames = new Dictionary();
int age = agesForNames["Bob"];
情景七 集合为null
public class Person {
    public string Name { get; set; }
}
var people = new List();
people.Add(null);
var names = from p in people select p.Name;
string firstName = names.First(); 

以上代码会在 names.First() 处理抛出异常,因为我们在

people.Add(null); 
添加了null值
情景八 事件(Event)为null
public class Demo
{
    public event EventHandler StateChanged;

    protected virtual void OnStateChanged(EventArgs e)
    {        
        StateChanged(this, e);
    }
}

如果外部实例没有注册 StateChanged 事件,那么调用 StateChanged(this, e); 会抛出NullReferenceException(未将对象引用到实例),修复方法:

public class Demo
{
    public event EventHandler StateChanged;

    protected virtual void OnStateChanged(EventArgs e)
    {      
        if(StateChanged != null)
        {  
            StateChanged(this, e);
        }
    }
}
情景九 重复的变量名

如果全局变量和局部变量的名称是一样的,那么你的全局变量就可能永远不会被赋值,如下:

public class Form1 {
    private Customer customer;

    private void Form1_Load(object sender, EventArgs e) {
        Customer customer = new Customer();
        customer.Name = "John";
    }

    private void Button_Click(object sender, EventArgs e) {
        MessageBox.Show(customer.Name);
    }
}

请使用不同的变量名称来修复:

private Customer _customer;    
情景二 ASP.NET生命周期
public partial class Issues_Edit : System.Web.UI.Page
{
    protected TestIssue myIssue;

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            // 只有页面首次加载时执行,点击按钮时不会被执行
            myIssue = new TestIssue(); 
        }
    }

    protected void SaveButton_Click(object sender, EventArgs e)
    {
        myIssue.Entry = "NullReferenceException here!";
    }
}
情景十一 ASP.NET Session的值为null
string firstName = Session["FirstName"].ToString();

如果Session["FirstName"]没有被赋值,则会抛出NullReferenceException(未将对象引用到实例)的异常。

情景十二 ASP.NET 视图模式为null
// Controller[控制器]
public class Restaurant:Controller
{
    public ActionResult Search()
    {
         return View();  // Forgot the provide a Model here.
    }
}

// Razor[视图页面]
@foreach (var restaurantSearch in Model.RestaurantSearch)  //抛出异常
{
}

@Model.somePropertyName

关于.NET[C#]中NullReferenceException(未将对象引用到实例)总结到这里,如果你遇到在不同的情景遇到同样的异常,欢迎反馈、交流。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/110497.html

相关文章

  • #yyds干货盘点# C#扩展方法

    摘要:定义用来扩展已定义类型中的方法成员在扩展方法之前,扩展一个方法需要使用继承来扩展现有类来扩展现有类型,并且值类型和密封类型是不能被继承的定义规则扩展方法的 定义用来扩展已定义类型中的方法成员在扩展方法之前,扩展一个方法需要使用继承来扩展现有类来扩展现有类型,并且值类型和密封类型(sealed)是不能被继承的定义规则扩展方法...

    马永翠 评论0 收藏0
  • 在mongovue里Add collection时错误(Error in creating new

    摘要:今天在里时发生错误,错误如下未将对象引用设置到对象的实例。适应于所有版本,的默认引擎仅支持位错误原因在之后默认的是引擎,而管理软件匹配的还是之前的引擎,所以无法使用,必须重置存引擎。 今天在mongovue里Add collection时发生错误,错误如下: Error in creating new Collection 未将对象引用设置到对象的实例。 Type: System.Nu...

    qpwoeiru96 评论0 收藏0
  • 递易技术部平台开发代码规范

    摘要:命名命名采取驼峰式,例如和大写,不要使用下划线。在开发过程中最常见异常的就是。但与函数不同的是函数以代码行数统计,而类以权责统计。第二原则是高内聚低耦合。 命名 命名采取驼峰式,例如:AccountName,A和N大写,不要使用下划线。命名包括变量、函数、参数,类等命名要能很好的表述其承载的业务。要名副其实,不存在歧义,要直截了当。 例子: 函数和参数 public Account...

    DC_er 评论0 收藏0
  • C# 将彩色PDF转为灰度PDF

    摘要:本文以代码为例介绍如何实现将彩色文件转为灰度黑白的文件,即将文档里面的彩色图片或者文字等通过调用方法转为文档页面为灰色调无彩色效果的文档。将以下内容复制到控制台安装。转彩色为灰度这里转换主要用到以下步骤使用类加载文件。 ​本文以C#代码为例介绍如何实现将彩色PDF文件转为灰度(黑白)的PDF文件,即将PDF文档里面的彩色图...

    番茄西红柿 评论0 收藏2637
  • Java - 收藏集 - 掘金

    摘要:强大的表单验证前端掘金支持非常强大的内置表单验证,以及。面向对象和面向过程的区别的种设计模式全解析后端掘金一设计模式的分类总体来说设计模式分为三大类创建型模式,共五种工厂方法模式抽象工厂模式单例模式建造者模式原型模式。 强大的 Angular 表单验证 - 前端 - 掘金Angular 支持非常强大的内置表单验证,maxlength、minlength、required 以及 patt...

    XiNGRZ 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<