zoukankan      html  css  js  c++  java
  • 星空雅梦

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

     后端开发  作者: Rector  1973 阅读  0 评论  0 收藏  收藏本文

    郑重申明:本文未经许可,禁止任何形式转载

    问题分析

    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(未将对象引用到实例)总结到这里,如果你遇到在不同的情景遇到同样的异常,欢迎反馈、交流。

     
  • 相关阅读:
    tkinter学习-Lable&Button
    Shell—常见报错问题
    Linux—修改ssh远程登录信息
    Linux—网络管理
    Linux—磁盘管理
    Python—创建进程的三种方式
    Shell—引入外部脚本文件
    Mysql—数据恢复
    Shell—文件内容操作
    Shell—各种括号的用法
  • 原文地址:https://www.cnblogs.com/LiZhongZhongY/p/10792460.html
Copyright © 2011-2022 走看看