NullReferenceException 类
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
尝试取消引用 null 对象引用时引发的异常。
public ref class NullReferenceException : Exception
public ref class NullReferenceException : SystemException
public class NullReferenceException : Exception
public class NullReferenceException : SystemException
[System.Serializable]
public class NullReferenceException : SystemException
[System.Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public class NullReferenceException : SystemException
type NullReferenceException = class
inherit Exception
type NullReferenceException = class
inherit SystemException
[<System.Serializable>]
type NullReferenceException = class
inherit SystemException
[<System.Serializable>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type NullReferenceException = class
inherit SystemException
Public Class NullReferenceException
Inherits Exception
Public Class NullReferenceException
Inherits SystemException
- 继承
- 继承
- 属性
注解
NullReferenceException尝试访问其值为null的类型上的成员时,将引发异常。 异常 NullReferenceException 通常反映开发人员错误,并在以下方案中引发:
Note
可以使用 null 条件运算符 () 或 null 合并运算符 (???.) 来避免 C# 中的大多数NullReferenceException异常。 有关详细信息,请参阅可为空的引用类型。 以下 C# 示例假定禁用可为 null 的上下文(不建议这样做)。
忘记实例化引用类型。 在下面的示例中,
names声明但从未实例化(受影响的行在 C# 示例中注释掉,因为它未编译):using System.Collections.Generic; public class UseBeforeAssignExample { public static void Main(string[] args) { int value = int.Parse(args[0]); List<string> names; if (value > 0) names = []; //names.Add("Major Major Major"); } } // Compilation displays a warning like the following: // warning BC42104: Variable //names// is used before it // has been assigned a value. A null reference exception could result // at runtime. // // names.Add("Major Major Major") // ~~~~~ // The example displays output like the following output: // Unhandled Exception: System.NullReferenceException: Object reference // not set to an instance of an object. // at UseBeforeAssignExample.Main()open System [<EntryPoint>] let main args = let value = Int32.Parse args[0] // Set names to null, don't initialize it. let mutable names = Unchecked.defaultof<ResizeArray<string>> if value > 0 then names <- ResizeArray() names.Add "Major Major Major" 0 // Compilation does not display a warning as this is an extremely rare occurance in F#. // Creating a value without initalizing either requires using 'null' (not possible // on types defined in F# without [<AllowNullLiteral>]) or Unchecked.defaultof. // // The example displays output like the following output: // Unhandled Exception: System.NullReferenceException: Object reference // not set to an instance of an object. // at Example.main()Imports System.Collections.Generic Module Example Public Sub Main() Dim names As List(Of String) names.Add("Major Major Major") End Sub End Module ' Compilation displays a warning like the following: ' Example1.vb(10) : warning BC42104: Variable 'names' is used before it ' has been assigned a value. A null reference exception could result ' at runtime. ' ' names.Add("Major Major Major") ' ~~~~~ ' The example displays output like the following output: ' Unhandled Exception: System.NullReferenceException: Object reference ' not set to an instance of an object. ' at Example.Main()某些编译器在编译此代码时发出警告。 其他人会发出错误,编译失败。 若要解决此问题,请实例化对象,使其值不再
null。 以下示例通过调用类型的类构造函数来执行此操作。using System.Collections.Generic; public class AnotherExample { public static void Main() { List<string> names = ["Major Major Major"]; } }let names = ResizeArray() names.Add "Major Major Major"Imports System.Collections.Generic Module Example Public Sub Main() Dim names As New List(Of String)() names.Add("Major Major Major") End Sub End Module在初始化数组之前,你忘记了对数组进行维度调整。 在下面的示例中,
values声明为整数数组,但从未指定包含的元素数。 因此,尝试初始化其值会引发异常 NullReferenceException 。int[] values = null; for (int ctr = 0; ctr <= 9; ctr++) values[ctr] = ctr * 2; foreach (int value in values) Console.WriteLine(value); // The example displays the following output: // Unhandled Exception: // System.NullReferenceException: Object reference not set to an instance of an object. // at Array3Example.Main()let values: int[] = null for i = 0 to 9 do values[i] <- i * 2 for value in values do printfn $"{value}" // The example displays the following output: // Unhandled Exception: // System.NullReferenceException: Object reference not set to an instance of an object. // at <StartupCode$fs>.main()Module Example Public Sub Main() Dim values() As Integer For ctr As Integer = 0 To 9 values(ctr) = ctr * 2 Next For Each value In values Console.WriteLine(value) Next End Sub End Module ' The example displays the following output: ' Unhandled Exception: ' System.NullReferenceException: Object reference not set to an instance of an object. ' at Example.Main()在初始化数组之前,可以通过声明数组中的元素数来消除异常,如以下示例所示。
int[] values = new int[10]; for (int ctr = 0; ctr <= 9; ctr++) values[ctr] = ctr * 2; foreach (int value in values) Console.WriteLine(value); // The example displays the following output: // 0 // 2 // 4 // 6 // 8 // 10 // 12 // 14 // 16 // 18let values = Array.zeroCreate<int> 10 for i = 0 to 9 do values[i] <- i * 2 for value in values do printfn $"{value}" // The example displays the following output: // 0 // 2 // 4 // 6 // 8 // 10 // 12 // 14 // 16 // 18Module Example Public Sub Main() Dim values(9) As Integer For ctr As Integer = 0 To 9 values(ctr) = ctr * 2 Next For Each value In values Console.WriteLine(value) Next End Sub End Module ' The example displays the following output: ' 0 ' 2 ' 4 ' 6 ' 8 ' 10 ' 12 ' 14 ' 16 ' 18从方法获取 null 返回值,然后在返回的类型上调用方法。 这有时是文档错误的结果;文档无法指出方法调用可以返回
null。 在其他情况下,代码错误地假定该方法将始终返回非 null 值。以下示例中的代码假定 Array.Find 该方法始终返回
Person其FirstName字段与搜索字符串匹配的对象。 由于没有匹配项,运行时会引发异常 NullReferenceException 。public static void NoCheckExample() { Person[] persons = Person.AddRange([ "Abigail", "Abra", "Abraham", "Adrian", "Ariella", "Arnold", "Aston", "Astor" ]); string nameToFind = "Robert"; Person found = Array.Find(persons, p => p.FirstName == nameToFind); Console.WriteLine(found.FirstName); } // The example displays the following output: // Unhandled Exception: System.NullReferenceException: // Object reference not set to an instance of an object.open System type Person(firstName) = member _.FirstName = firstName static member AddRange(firstNames) = Array.map Person firstNames let persons = [| "Abigail"; "Abra"; "Abraham"; "Adrian" "Ariella"; "Arnold"; "Aston"; "Astor" |] |> Person.AddRange let nameToFind = "Robert" let found = Array.Find(persons, fun p -> p.FirstName = nameToFind) printfn $"{found.FirstName}" // The example displays the following output: // Unhandled Exception: System.NullReferenceException: // Object reference not set to an instance of an object. // at <StartupCode$fs>.main()Module Example Public Sub Main() Dim persons() As Person = Person.AddRange( { "Abigail", "Abra", "Abraham", "Adrian", "Ariella", "Arnold", "Aston", "Astor" } ) Dim nameToFind As String = "Robert" Dim found As Person = Array.Find(persons, Function(p) p.FirstName = nameToFind) Console.WriteLine(found.FirstName) End Sub End Module Public Class Person Public Shared Function AddRange(firstNames() As String) As Person() Dim p(firstNames.Length - 1) As Person For ctr As Integer = 0 To firstNames.Length - 1 p(ctr) = New Person(firstNames(ctr)) Next Return p End Function Public Sub New(firstName As String) Me.FirstName = firstName End Sub Public FirstName As String End Class ' The example displays the following output: ' Unhandled Exception: System.NullReferenceException: ' Object reference not set to an instance of an object. ' at Example.Main()若要解决此问题,请测试方法的返回值,以确保它不是在
null调用其任何成员之前,如以下示例所示。public static void ExampleWithNullCheck() { Person[] persons = Person.AddRange([ "Abigail", "Abra", "Abraham", "Adrian", "Ariella", "Arnold", "Aston", "Astor" ]); string nameToFind = "Robert"; Person found = Array.Find(persons, p => p.FirstName == nameToFind); if (found != null) Console.WriteLine(found.FirstName); else Console.WriteLine($"'{nameToFind}' not found."); } // The example displays the following output: // 'Robert' not foundopen System [<AllowNullLiteral>] type Person(firstName) = member _.FirstName = firstName static member AddRange(firstNames) = Array.map Person firstNames let persons = [| "Abigail"; "Abra"; "Abraham"; "Adrian" "Ariella"; "Arnold"; "Aston"; "Astor" |] |> Person.AddRange let nameToFind = "Robert" let found = Array.Find(persons, fun p -> p.FirstName = nameToFind) if found <> null then printfn $"{found.FirstName}" else printfn $"{nameToFind} not found." // Using F#'s Array.tryFind function // This does not require a null check or [<AllowNullLiteral>] let found2 = persons |> Array.tryFind (fun p -> p.FirstName = nameToFind) match found2 with | Some firstName -> printfn $"{firstName}" | None -> printfn $"{nameToFind} not found." // The example displays the following output: // Robert not found. // Robert not found.Module Example Public Sub Main() Dim persons() As Person = Person.AddRange( { "Abigail", "Abra", "Abraham", "Adrian", "Ariella", "Arnold", "Aston", "Astor" } ) Dim nameToFind As String = "Robert" Dim found As Person = Array.Find(persons, Function(p) p.FirstName = nameToFind) If found IsNot Nothing Then Console.WriteLine(found.FirstName) Else Console.WriteLine("{0} not found.", nameToFind) End If End Sub End Module Public Class Person Public Shared Function AddRange(firstNames() As String) As Person() Dim p(firstNames.Length - 1) As Person For ctr As Integer = 0 To firstNames.Length - 1 p(ctr) = New Person(firstNames(ctr)) Next Return p End Function Public Sub New(firstName As String) Me.FirstName = firstName End Sub Public FirstName As String End Class ' The example displays the following output: ' Robert not found你正在使用表达式(例如,将方法或属性列表链接在一起)来检索值,尽管正在检查该值是否是
null,但运行时仍会引发异常 NullReferenceException 。 之所以发生这种情况,是因为表达式中的一个中间值返回null。 因此,永远不会评估你的null测试。以下示例定义一个
Pages对象,该对象缓存有关由对象呈现Page的网页的信息。 该方法Example.Main检查当前网页是否具有非 null 标题,如果存在,则显示标题。 但是,尽管有此检查,但该方法会引发异常 NullReferenceException 。public class Chain1Example { public static void Main() { var pages = new Pages(); if (!string.IsNullOrEmpty(pages.CurrentPage.Title)) { string title = pages.CurrentPage.Title; Console.WriteLine($"Current title: '{title}'"); } } } public class Pages { readonly Page[] _page = new Page[10]; int _ctr = 0; public Page CurrentPage { get { return _page[_ctr]; } set { // Move all the page objects down to accommodate the new one. if (_ctr > _page.GetUpperBound(0)) { for (int ndx = 1; ndx <= _page.GetUpperBound(0); ndx++) _page[ndx - 1] = _page[ndx]; } _page[_ctr] = value; if (_ctr < _page.GetUpperBound(0)) _ctr++; } } public Page PreviousPage { get { if (_ctr == 0) { if (_page[0] is null) return null; else return _page[0]; } else { _ctr--; return _page[_ctr + 1]; } } } } public class Page { public Uri URL; public string Title; } // The example displays the following output: // Unhandled Exception: // System.NullReferenceException: Object reference not set to an instance of an object. // at Chain1Example.Main()open System type Page() = [<DefaultValue>] val mutable public URL: Uri [<DefaultValue>] val mutable public Title: string type Pages() = let pages = Array.zeroCreate<Page> 10 let mutable i = 0 member _.CurrentPage with get () = pages[i] and set (value) = // Move all the page objects down to accommodate the new one. if i > pages.GetUpperBound 0 then for ndx = 1 to pages.GetUpperBound 0 do pages[ndx - 1] <- pages[ndx] pages[i] <- value if i < pages.GetUpperBound 0 then i <- i + 1 member _.PreviousPage = if i = 0 then if box pages[0] = null then Unchecked.defaultof<Page> else pages[0] else i <- i - 1 pages[i + 1] let pages = Pages() if String.IsNullOrEmpty pages.CurrentPage.Title |> not then let title = pages.CurrentPage.Title printfn $"Current title: '{title}'" // The example displays the following output: // Unhandled Exception: // System.NullReferenceException: Object reference not set to an instance of an object. // at <StartupCode$fs>.main()Module Example Public Sub Main() Dim pages As New Pages() Dim title As String = pages.CurrentPage.Title End Sub End Module Public Class Pages Dim page(9) As Page Dim ctr As Integer = 0 Public Property CurrentPage As Page Get Return page(ctr) End Get Set ' Move all the page objects down to accommodate the new one. If ctr > page.GetUpperBound(0) Then For ndx As Integer = 1 To page.GetUpperBound(0) page(ndx - 1) = page(ndx) Next End If page(ctr) = value If ctr < page.GetUpperBound(0) Then ctr += 1 End Set End Property Public ReadOnly Property PreviousPage As Page Get If ctr = 0 Then If page(0) Is Nothing Then Return Nothing Else Return page(0) End If Else ctr -= 1 Return page(ctr + 1) End If End Get End Property End Class Public Class Page Public URL As Uri Public Title As String End Class ' The example displays the following output: ' Unhandled Exception: ' System.NullReferenceException: Object reference not set to an instance of an object. ' at Example.Main()引发异常的原因是
pages.CurrentPage,如果未在缓存中存储任何页面信息,则null返回。 通过在检索当前Page对象的Title属性之前测试属性的值CurrentPage来更正此异常,如以下示例所示:var pages = new Pages(); Page current = pages.CurrentPage; if (current != null) { string title = current.Title; Console.WriteLine($"Current title: '{title}'"); } else { Console.WriteLine("There is no page information in the cache."); } // The example displays the following output: // There is no page information in the cache.let pages = Pages() let current = pages.CurrentPage if box current <> null then let title = current.Title printfn $"Current title: '{title}'" else printfn "There is no page information in the cache." // The example displays the following output: // There is no page information in the cache.Module Example Public Sub Main() Dim pages As New Pages() Dim current As Page = pages.CurrentPage If current IsNot Nothing Then Dim title As String = current.Title Console.WriteLine("Current title: '{0}'", title) Else Console.WriteLine("There is no page information in the cache.") End If End Sub End Module ' The example displays the following output: ' There is no page information in the cache.你正在枚举包含引用类型的数组的元素,并且尝试处理其中一个 NullReferenceException 元素会引发异常。
以下示例定义字符串数组。 语句
for枚举数组中的元素,并在显示字符串之前调用每个字符串 Trim 的方法。string[] values = [ "one", null, "two" ]; for (int ctr = 0; ctr <= values.GetUpperBound(0); ctr++) Console.Write("{0}{1}", values[ctr].Trim(), ctr == values.GetUpperBound(0) ? "" : ", "); Console.WriteLine(); // The example displays the following output: // Unhandled Exception: // System.NullReferenceException: Object reference not set to an instance of an object.open System let values = [| "one"; null; "two" |] for i = 0 to values.GetUpperBound 0 do printfn $"""{values[i].Trim()}{if i = values.GetUpperBound 0 then "" else ", "}""" printfn "" // The example displays the following output: // Unhandled Exception: // System.NullReferenceException: Object reference not set to an instance of an object. // at <StartupCode$fs>.main()Module Example Public Sub Main() Dim values() As String = { "one", Nothing, "two" } For ctr As Integer = 0 To values.GetUpperBound(0) Console.Write("{0}{1}", values(ctr).Trim(), If(ctr = values.GetUpperBound(0), "", ", ")) Next Console.WriteLine() End Sub End Module ' The example displays the following output: ' Unhandled Exception: System.NullReferenceException: ' Object reference not set to an instance of an object. ' at Example.Main()如果假定数组的每个元素必须包含非 null 值,并且数组元素的值实际上是
null这样,则会发生此异常。 通过测试元素是否在该null元素上执行任何操作之前,可以消除该异常,如以下示例所示。string[] values = [ "one", null, "two" ]; for (int ctr = 0; ctr <= values.GetUpperBound(0); ctr++) Console.Write("{0}{1}", values[ctr] != null ? values[ctr].Trim() : "", ctr == values.GetUpperBound(0) ? "" : ", "); Console.WriteLine(); // The example displays the following output: // one, , twoopen System let values = [| "one"; null; "two" |] for i = 0 to values.GetUpperBound 0 do printf $"""{if values[i] <> null then values[i].Trim() else ""}{if i = values.GetUpperBound 0 then "" else ", "}""" Console.WriteLine() // The example displays the following output: // one, , twoModule Example Public Sub Main() Dim values() As String = { "one", Nothing, "two" } For ctr As Integer = 0 To values.GetUpperBound(0) Console.Write("{0}{1}", If(values(ctr) IsNot Nothing, values(ctr).Trim(), ""), If(ctr = values.GetUpperBound(0), "", ", ")) Next Console.WriteLine() End Sub End Module ' The example displays the following output: ' one, , two当该方法访问其某个参数的成员时,该方法是
null。PopulateNames以下示例中的方法在行names.Add(arrName);中引发异常。using System.Collections.Generic; public class NRE2Example { public static void Main() { List<string> names = GetData(); PopulateNames(names); } private static void PopulateNames(List<string> names) { string[] arrNames = [ "Dakota", "Samuel", "Nikita", "Koani", "Saya", "Yiska", "Yumaevsky" ]; foreach (string arrName in arrNames) names.Add(arrName); } private static List<string> GetData() { return null; } } // The example displays output like the following: // Unhandled Exception: System.NullReferenceException: Object reference // not set to an instance of an object. // at NRE2Example.PopulateNames(List`1 names) // at NRE2Example.Main()let populateNames (names: ResizeArray<string>) = let arrNames = [ "Dakota"; "Samuel"; "Nikita" "Koani"; "Saya"; "Yiska"; "Yumaevsky" ] for arrName in arrNames do names.Add arrName let getData () : ResizeArray<string> = null let names = getData () populateNames names // The example displays output like the following: // Unhandled Exception: System.NullReferenceException: Object reference // not set to an instance of an object. // at Example.PopulateNames(List`1 names) // at <StartupCode$fs>.main()Imports System.Collections.Generic Module Example Public Sub Main() Dim names As List(Of String) = GetData() PopulateNames(names) End Sub Private Sub PopulateNames(names As List(Of String)) Dim arrNames() As String = { "Dakota", "Samuel", "Nikita", "Koani", "Saya", "Yiska", "Yumaevsky" } For Each arrName In arrNames names.Add(arrName) Next End Sub Private Function GetData() As List(Of String) Return Nothing End Function End Module ' The example displays output like the following: ' Unhandled Exception: System.NullReferenceException: Object reference ' not set to an instance of an object. ' at Example.PopulateNames(List`1 names) ' at Example.Main()若要解决此问题,请确保传递给方法的参数不是
null,或处理块中引发的try…catch…finally异常。 有关详细信息,请参阅 异常。创建列表时不知道该类型,并且列表未初始化。
GetList以下示例中的方法在行emptyList.Add(value)中引发异常。using System; using System.Collections.Generic; using System.Collections; using System.Runtime.Serialization; public class NullReferenceExample { public static void Main() { var listType = GetListType(); _ = GetList(listType); } private static Type GetListType() { return typeof(List<int>); } private static IList GetList(Type type) { var emptyList = (IList)FormatterServices.GetUninitializedObject(type); // Does not call list constructor var value = 1; emptyList.Add(value); return emptyList; } } // The example displays output like the following: // Unhandled Exception: System.NullReferenceException: 'Object reference // not set to an instance of an object.' // at System.Collections.Generic.List`1.System.Collections.IList.Add(Object item) // at NullReferenceExample.GetList(Type type): line 24若要解决此问题,请确保列表已初始化(执行此操作的一种方法是调用而不是
FormatterServices.GetUninitializedObject调用Activator.CreateInstance),或处理块中引发的try…catch…finally异常。 有关详细信息,请参阅 异常。
以下Microsoft中间语言(MSIL)指令引发 NullReferenceException:callvirt, cpblk、cpobj、initblk、ldelem.<type>、ldelema、ldfld、ldflda、 ldind.<type>、ldlen、stelem.<type>、stfld、stind.<type>、throw 和 unbox。
NullReferenceException 使用具有值0x80004003的 HRESULT COR_E_NULLREFERENCE。
有关实例 NullReferenceException的初始属性值列表,请参阅 NullReferenceException 构造函数。
何时处理 NullReferenceException 异常
通常最好避免 NullReferenceException 而不是在发生 NullReferenceException 之后处理它。 处理异常会使代码难以维护和理解,有时可能会引入其他 bug。 NullReferenceException 通常是不可恢复的错误。 在这些情况下,让异常停止应用可能是最佳替代方法。
但是,在处理错误时,有许多情况非常有用:
你的应用可以忽略为 null 的对象。 例如,如果应用检索并处理数据库中的记录,则你可能能够忽略导致 null 对象的一些错误记录。 在日志文件或应用程序 UI 中记录不良数据可能是必须做的。
可以从异常中恢复。 例如,如果连接丢失或连接超时,则返回引用类型的 Web 服务的调用可能会返回 null。可以尝试重新建立连接,然后再次尝试调用。
可以将应用的状态还原到有效状态。 例如,在调用引发 NullReferenceException 的方法之前,可能需要将信息保存到数据存储的多步骤任务。 如果未初始化的对象会损坏数据记录,则可以在关闭应用之前删除以前的数据。
你想要报告异常。 例如,如果错误是由应用用户的错误引起的,则可以生成一条消息来帮助他们提供正确的信息。 还可以记录有关错误的信息,以帮助解决问题。 某些框架(如 ASP.NET)具有一个高级异常处理程序,用于捕获应用从未崩溃的所有错误;在这种情况下,日志记录异常可能是你唯一知道它发生的方式。
构造函数
| 名称 | 说明 |
|---|---|
| NullReferenceException() |
初始化类的新实例 NullReferenceException ,将新实例的属性设置为 Message 描述错误的系统提供的消息,例如“在需要对象实例的位置找到值'null'”。此消息将考虑当前系统区域性。 |
| NullReferenceException(SerializationInfo, StreamingContext) |
已过时.
使用序列化的数据初始化 NullReferenceException 类的新实例。 |
| NullReferenceException(String, Exception) |
使用指定的错误消息和对作为此异常原因的内部异常的引用初始化 NullReferenceException 类的新实例。 |
| NullReferenceException(String) |
使用指定的错误消息初始化类的新实例 NullReferenceException 。 |
属性
| 名称 | 说明 |
|---|---|
| Data |
获取键/值对的集合,这些键/值对提供有关异常的其他用户定义的信息。 (继承自 Exception) |
| HelpLink |
获取或设置与此异常关联的帮助文件的链接。 (继承自 Exception) |
| HResult |
获取或设置 HRESULT,它是分配给特定异常的编码数值。 (继承自 Exception) |
| InnerException |
Exception获取导致当前异常的实例。 (继承自 Exception) |
| Message |
获取描述当前异常的消息。 (继承自 Exception) |
| Source |
获取或设置导致错误的应用程序或对象的名称。 (继承自 Exception) |
| StackTrace |
获取调用堆栈上即时帧的字符串表示形式。 (继承自 Exception) |
| TargetSite |
获取引发当前异常的方法。 (继承自 Exception) |
方法
| 名称 | 说明 |
|---|---|
| Equals(Object) |
确定指定对象是否等于当前对象。 (继承自 Object) |
| GetBaseException() |
在派生类中重写时,返回 Exception 一个或多个后续异常的根本原因。 (继承自 Exception) |
| GetHashCode() |
用作默认哈希函数。 (继承自 Object) |
| GetObjectData(SerializationInfo, StreamingContext) |
已过时.
在派生类中重写时,设置 SerializationInfo 有关异常的信息。 (继承自 Exception) |
| GetType() |
获取当前实例的运行时类型。 (继承自 Exception) |
| MemberwiseClone() |
创建当前 Object的浅表副本。 (继承自 Object) |
| ToString() |
创建并返回当前异常的字符串表示形式。 (继承自 Exception) |
活动
| 名称 | 说明 |
|---|---|
| SerializeObjectState |
已过时.
序列化异常以创建包含有关异常的序列化数据的异常状态对象时发生。 (继承自 Exception) |