问题分析
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<String> names;
names.Add("Major Major Major");
}
}
此例中的 names在使用之前并没有初始化,修复后的:
using System;
using System.Collections.Generic;
public class Example
{
public static void Main()
{
List<String> names = new List<String>();
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<string, int> agesForNames = null;
int age = agesForNames["Bob"];
这里的 agesForNames字典为 null,抛出NullReferenceException(未将对象引用到实例)的异常,使用new关键字来初始化:
Dictionary<string, int> agesForNames = new Dictionary<string, int>();
int age = agesForNames["Bob"];
情景七 集合为null
public class Person {
public string Name { get; set; }
}
var people = new List<Person>();
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) //抛出异常
{
}
<p>@Model.somePropertyName</p> <!-- 抛出异常 -->
关于.NET[C#]中NullReferenceException(未将对象引用到实例)总结到这里,如果你遇到在不同的情景遇到同样的异常,欢迎反馈、交流。