What is a NullReferenceException, and how do I fix it?
我有一些代码,当它执行时,它抛出一个
Object reference not set to an instance of an object.
这意味着什么?我该怎么做来修复这个错误?
原因是什么?底线
您试图使用的是
像其他任何东西一样,
注意,通过
本文的其余部分将更详细地介绍并显示许多程序员经常犯的错误,这些错误可能导致
抛出
这意味着引用是
1 2 | string foo = null; foo.ToUpper(); |
这将在第二行抛出一个
你如何找到
如果要查找引用的位置,请右键单击其名称并选择"查找所有引用"。然后可以在每个找到的位置放置一个断点,并在附加了调试器的情况下运行程序。每当调试器在这样一个断点上中断时,您需要确定您是否希望引用为非空,检查变量,并验证它是否在您期望的时候指向实例。好的。
通过这样遵循程序流,您可以找到实例不应为空的位置以及未正确设置实例的原因。好的。实例
可以引发异常的一些常见情况:好的。通用的
1 | ref1.ref2.ref3.member |
如果ref1、ref2或ref3为空,则会得到一个
1 2 3 4 | var r1 = ref1; var r2 = r1.ref2; var r3 = r2.ref3; r3.member |
具体来说,在
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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; // You never initialized the Author property. // there is no Person to get an Age from. } } |
如果要避免子(person)空引用,可以在父(book)对象的构造函数中对其进行初始化。好的。嵌套对象初始值设定项
这同样适用于嵌套对象初始值设定项:好的。
1 |
这就意味着好的。
1 2 |
虽然使用了
1 2 3 4 5 6 | public class Person { public ICollection<Book> Books { get; set; } } public class Book { public string Title { get; set; } } |
嵌套集合初始化器的表现一样。
好。
1 2 3 4 5 6 |
这两个translates
好。
1 2 3 |
《
好。 阵列
1 2 | int[] numbers = null; int n = numbers[0]; // numbers is null. There is no array to index. |
数组元素
1 2 3 | Person[] people = new Person[5]; people[0].Age = 20 // people[0] is null. The array was allocated but not // initialized. There is no Person to set the Age for. |
jagged阵列
1 2 3 | long[][] array = new long[1][]; array[0][0] = 3; // is null because only the first dimension is yet initialized. // Use array[0] = new long[2]; first. |
收集/战略/词典
1 2 3 | Dictionary<string, int> agesForNames = null; int age = agesForNames["Bob"]; // agesForNames is null. // There is no Dictionary to perform the lookup. |
(范围可变间接/ deferred)
1 2 3 4 5 6 7 8 9 | 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(); // Exception is thrown here, but actually occurs // on the line above. "p" is null because the // first element we added to the list is null. |
事件
1 2 3 4 5 6 7 8 9 10 11 | public class Demo { public event EventHandler StateChanged; protected virtual void OnStateChanged(EventArgs e) { StateChanged(this, e); // Exception is thrown here // if no event handlers have been attached // to StateChanged event } } |
问:命名公约
如果你从"字段differently locals,你可能永远不会知道,你的initialized场。
好。
1 2 3 4 5 6 7 8 9 10 11 12 | 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); } } |
这可能是solved市以下两个领域的会议和underscore字头:
好。
1 | private Customer _customer; |
ASP.NET页生命周期:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public partial class Issues_Edit : System.Web.UI.Page { protected TestIssue myIssue; protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // Only called on first load, not when button clicked myIssue = new TestIssue(); } } protected void SaveButton_Click(object sender, EventArgs e) { myIssue.Entry ="NullReferenceException here!"; } } |
ASP.NET会话值
1 2 3 | // if the"FirstName" session value has not yet been set, // then this line will throw a NullReferenceException string firstName = Session["FirstName"].ToString(); |
ASP.NET MVC的View的空模型
如果出现例外,当一部
好。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // Controller public class Restaurant:Controller { public ActionResult Search() { return View(); // Forgot the provide a Model here. } } // Razor view @foreach (var restaurantSearch in Model.RestaurantSearch) // Throws. { } <p> @Model.somePropertyName </p>Ok. <!-- Also throws --> |
wpf创造秩序和控制。
wpf Controls是创造了在
好。
例如:
好。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <Grid> <!-- Combobox declared first --> <ComboBox Name="comboBox1" Margin="10" SelectedIndex="0" SelectionChanged="comboBox1_SelectionChanged"> <ComboBoxItem Content="Item 1" /> <ComboBoxItem Content="Item 2" /> <ComboBoxItem Content="Item 3" /> </ComboBox> <!-- Label declared later --> <Label Name="label1" Content="Label" Margin="10" /> </Grid> |
在这里创造了
好。
1 2 3 4 | private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e) { label1.Content = comboBox1.SelectedIndex.ToString(); // NullReference here!! } |
变化的阶的XAML声明的(即,listing
好。 铸造用
1 | var myThing = someObject as Thing; |
这不是把一个invalidcastexception归来
好。 firstordefault(LINQ)和singleordefault()
《平原
好。 foreach
当你
好。
1 2 | List<int> list = null; foreach(var v in list) { } // exception |
享受realistic实例——选择节点从XML文件。如果是会把节点的初始调试,但没有发现有效的节目,所有的属性:
好。
1 | foreach (var node in myData.MyXml.DocumentNode.SelectNodes("//Data")) |
两种方式,避 没有检查和
如果你期望的参考,有时是空的,你可以检查网络访问
好。
1 2 3 4 5 | void PrintName(Person p) { if (p != null) { Console.WriteLine(p.Name); } } |
没有支票和一
你期望的两个方法调用返回的实例可以返回
好。
1 2 3 4 5 | string GetCategory(Book b) { if (b == null) return"Unknown"; return b.Category; } |
没有检查方法和要求,从
你可以把一个自定义例外也只抓住它的呼叫代码:
好。
1 2 3 4 5 6 | string GetCategory(string bookTitle) { var book = library.FindBook(bookTitle); // This may return null if (book == null) throw new BookNotFoundException(bookTitle); // Your custom exception return book.Category; } |
如果一个使用
当你知道在开发这一方法也许可以,但不应该
好。
1 2 3 4 5 6 7 8 9 10 11 | string GetTitle(int knownBookID) { // You know this should never return null. var book = library.GetBook(knownBookID); // Exception will occur on the next line instead of at the end of this method. Debug.Assert(book != null,"Library didn't return a book for known book ID."); // Some other code return book.Title; // Will never throw NullReferenceException in Debug mode. } |
虽然这种检查不会在您的发布版本中结束,但会导致它在运行时处于发布模式时再次抛出
1 2 3 4 5 6 7 | DateTime? appointment = null; Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now)); // Will display the default value provided (DateTime.Now), because appointment is null. appointment = new DateTime(2022, 10, 20); Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now)); // Will display the appointment date, not the default |
使用空合并运算符:
当遇到
1 2 3 4 5 6 7 8 | IService CreateService(ILogger log, Int32? frobPowerLevel) { var serviceImpl = new MyService(log ?? NullLog.Instance); // Note that the above"GetValueOrDefault()" can also be rewritten to use // the coalesce operator: serviceImpl.FrobPowerLevel = frobPowerLevel ?? 5; } |
对数组使用空条件运算符:
这有时也被称为安全导航或ELVIS(在其形状之后)操作员。如果运算符左侧的表达式为空,则不会计算右侧的表达式,而是返回空值。这意味着像这样的情况:好的。
1 | var title = person.Title.ToUpper(); |
如果此人没有标题,这将引发异常,因为它试图对值为空的属性调用
在C 5及以下,可通过以下方式进行防护:好的。
1 | var title = person.Title == null ? null : person.Title.ToUpper(); |
现在,标题变量将为空,而不是引发异常。C 6为此引入了较短的语法:好的。
1 | var title = person.Title?.ToUpper(); |
这将导致标题变量为
当然,您仍然需要检查
1 2 3 4 5 6 7 | // regular null check int titleLength = 0; if (title != null) titleLength = title.Length; // If title is null, this would throw NullReferenceException // combining the `?` and the `??` operator int titleLength = title?.Length ?? 0; |
同样,对于阵列,可以使用
1 2 3 4 | int[] myIntArray=null; var i=5; int? elem = myIntArray?[i]; if (!elem.HasValue) Console.WriteLine("No value"); |
这将执行以下操作:如果myIntaray为空,则表达式返回空值,您可以安全地检查它。如果它包含一个数组,它将执行以下操作:
C支持"迭代器块"(在其他一些流行语言中称为"生成器")。由于延迟执行,在迭代器块中调试空解引用异常可能特别困难:好的。
1 2 3 4 5 6 7 8 9 10 | public IEnumerable<Frob> GetFrobs(FrobFactory f, int count) { for (int i = 0; i < count; ++i) yield return f.MakeFrob(); } ... FrobFactory factory = whatever; IEnumerable<Frobs> frobs = GetFrobs(); ... foreach(Frob frob in frobs) { ... } |
如果
1 2 3 4 5 6 7 8 | // DON'T DO THIS public IEnumerable<Frob> GetFrobs(FrobFactory f, int count) { if (f == null) throw new ArgumentNullException("f","factory must not be null"); for (int i = 0; i < count; ++i) yield return f.MakeFrob(); } |
为什么这是错误的?因为迭代器块在
通过这样编写一个空检查,您可以防止空引用,但是您将空参数异常移动到迭代点,而不是调用点,这对于调试来说非常混乱。好的。
正确的解决方法是:好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // DO THIS public IEnumerable<Frob> GetFrobs(FrobFactory f, int count) { // No yields in a public method that throws! if (f == null) throw new ArgumentNullException("f","factory must not be null"); return GetFrobsForReal(f, count); } private IEnumerable<Frob> GetFrobsForReal(FrobFactory f, int count) { // Yields in a private method Debug.Assert(f != null); for (int i = 0; i < count; ++i) yield return f.MakeFrob(); } |
也就是说,生成具有迭代器块逻辑的私有helper方法,以及执行空检查并返回迭代器的公共surface方法。现在,当调用
如果您检查linq-to对象的引用源,您将看到在整个过程中都使用了这种技术。写起来有点笨拙,但它使调试无效错误变得容易得多。优化代码是为了方便调用者,而不是为了方便作者。好的。关于不安全代码中空解引用的注释
C有一个"不安全"模式,顾名思义,这是非常危险的,因为提供内存安全和类型安全的正常安全机制没有被强制执行。你不应该写不安全的代码,除非你对内存的工作方式有一个透彻和深入的理解。好的。
在不安全模式下,您应该了解两个重要事实:好的。
- 取消对空指针的引用会产生与取消对空引用的引用相同的异常。
- 取消对无效非空指针的引用会产生该异常在某些情况下
为了理解这是为什么,首先理解.NET是如何产生空的取消引用异常的。(这些详细信息适用于在Windows上运行的.NET;其他操作系统使用类似的机制。)好的。
内存在Windows中被虚拟化;每个进程都获得一个由操作系统跟踪的内存的多个"页面"的虚拟内存空间。内存的每一页上都设置了标志,这些标志决定了如何使用内存:读取、写入、执行等等。最低的一页被标记为"如果以任何方式使用都会产生错误"。好的。
C中的空指针和空引用在内部都表示为数字零,因此任何试图将其取消引用到相应内存存储中的操作系统都会产生错误。然后.NET运行时检测到该错误并将其转换为空的取消引用异常。好的。
这就是取消对空指针和空引用的引用会产生相同异常的原因。好的。
第二点呢?取消引用落在虚拟内存最低页中的任何无效指针都会导致相同的操作系统错误,从而导致相同的异常。好的。
这为什么有意义?好吧,假设我们有一个包含两个int的结构,一个非托管指针等于空。如果我们试图取消对结构中第二个int的引用,clr将不会尝试访问位置0处的存储;它将访问位置4处的存储。但从逻辑上讲,这是一个空的取消引用,因为我们是通过空访问该地址的。好的。
如果您正在处理不安全的代码,并且您得到一个空的取消引用异常,请注意,有问题的指针不必为空。它可以是最低页面中的任何位置,并且将生成此异常。好的。好啊。
空引用异常-Visual Basic
VisualBasic的
此答案将使用Visual Basic术语、语法和上下文。使用的示例来自大量过去的堆栈溢出问题。这是为了通过使用帖子中经常出现的各种情况来最大限度地提高相关性。对于那些可能需要它的人,还提供了更多的解释。这里很可能列出了一个类似于您的示例。好的。
注:好的。
基本含义
消息"object not set to an instance of object"(对象未设置为对象的实例)表示您正在尝试使用尚未初始化的对象。这可以归结为:好的。
- 您的代码声明了一个对象变量,但它没有初始化它(创建一个实例或"实例化"它)。
- 您的代码假定某个对象会初始化,但没有
- 可能,其他代码过早地使仍在使用的对象无效
找到原因
由于问题是一个对象引用,即
好的。
您还应该从相关代码中删除任何try/catch块,尤其是在catch块中没有任何内容的代码中。这将导致代码在试图使用
在显示
您还可以使用
一旦你知道问题是什么和在哪里,解决问题通常相当容易,而且比发布一个新问题要快。好的。
参见:好的。
- 断点
- msdn:如何:使用try/catch块捕获异常
- msdn:例外情况的最佳实践
示例和补救措施类对象/创建实例
1 2 3 | Dim reg As CashRegister ... TextBox1.Text = reg.Amount ' NRE |
问题是,
补救方法好的。
当您声明实例时,通常可以使用
1 2 3 4 |
如果以后只适合创建实例:好的。
1 2 3 | Private reg As CashRegister ' Declare ... reg = New CashRegister() ' Create instance |
注意:不要在一个过程中再次使用
1 2 3 4 5 6 7 |
这将创建一个局部变量,
缺少
VisualBasic尝试使用
很明显,
有关详细信息,请参阅:好的。
- 新算子
- Visual Basic中的范围
- Visual Basic中的访问级别
- 值类型和引用类型
数组
数组也必须实例化:好的。
1 | Private arr as String() |
此数组仅已声明,未创建。初始化数组有几种方法:好的。
1 2 3 4 5 6 |
注:从vs 2010开始,当使用literal和
1 2 3 | Dim myDbl As Double() = {1.5, 2, 9.9, 18, 3.14} Dim myDbl = New Double() {1.5, 2, 9.9, 18, 3.14} Dim myDbl() = {1.5, 2, 9.9, 18, 3.14} |
数据类型和数组大小是根据所分配的数据推断出来的。类/模块级声明仍然需要使用
1 | Private myDoubles As Double() = {1.5, 2, 9.9, 18, 3.14} |
示例:类对象数组好的。
1 2 3 4 5 | Dim arrFoo(5) As Foo For i As Integer = 0 To arrFoo.Count - 1 arrFoo(i).Bar = i * 10 ' Exception Next |
数组已创建,但其中的
补救方法好的。
1 2 3 4 | For i As Integer = 0 To arrFoo.Count - 1 arrFoo(i) = New Foo() ' Create Foo instance arrFoo(i).Bar = i * 10 Next |
使用
1 2 3 4 5 6 7 8 |
有关详细信息,请参阅:好的。
- 期权推断声明
- Visual Basic中的范围
- Visual Basic中的数组
列表和集合
.NET集合(其中有许多变体-列表、字典等)也必须实例化或创建。好的。
1 2 3 | Private myList As List(Of String) .. myList.Add("ziggy") ' NullReference |
由于同样的原因,您会得到相同的异常——只声明了
1 2 3 4 | myList = New List(Of String) ' Or create an instance when declared: Private myList As New List(Of String) |
共同监督是使用集合
1 2 3 4 5 6 7 8 9 10 11 12 | Public Class Foo Private barList As List(Of Bar) Friend Function BarCount As Integer Return barList.Count End Function Friend Sub AddItem(newBar As Bar) If barList.Contains(newBar) = False Then barList.Add(newBar) End If End Function |
任何一个过程都将导致nre,因为
1 2 3 4 |
和以前一样,这是不正确的:好的。
1 2 3 4 | Public Sub New() ' Creates another barList local to this procedure Dim barList As New List(Of Bar) End Sub |
有关更多信息,请参见
使用数据库提供了许多空引用的机会,因为可以同时使用许多对象(
例1好的。
1 2 3 4 5 6 7 8 9 10 11 | Dim da As OleDbDataAdapter Dim ds As DataSet Dim MaxRows As Integer con.Open() Dim sql ="SELECT * FROM tblfoobar_List" da = New OleDbDataAdapter(sql, con) da.Fill(ds,"foobar") con.Close() MaxRows = ds.Tables("foobar").Rows.Count ' Error |
和以前一样,声明了
好的。
当声明为模块/类级变量时,如
补救方法好的。
1 | Dim ds As New DataSet |
例2好的。
1 2 3 4 5 6 |
打字错误是一个问题:
补救方法好的。
因为它使用一个表,所以使用
1 2 3 4 | If ds.Tables(0).Rows.Count > 0 Then txtID.Text = ds.Tables(0).Rows(0).Item(1) txtID.Name = ds.Tables(0).Rows(0).Item(2) End If |
1 | If da.Fill(ds,"Employees") > 0 Then... |
例3好的。
1 2 3 4 5 6 7 |
补救方法相同,按索引参考表:好的。
1 | If ds.Tables(0).Rows.Count > 0 Then |
另请参见DataTable类。好的。对象路径/嵌套
1 2 | If myFoo.Bar.Items IsNot Nothing Then ... |
代码只测试
1 2 3 4 | If (myFoo IsNot Nothing) AndAlso (myFoo.Bar IsNot Nothing) AndAlso (myFoo.Bar.Items IsNot Nothing) Then .... |
1 | myBase.myNodes(3).Layer.SubLayer.Foo.Files.Add("somefilename") |
不可能引用
1 | myWebBrowser.Document.GetElementById("formfld1").InnerText ="some value" |
在这里,
1 2 3 4 5 6 | Dim cmd5 As New SqlCommand("select Cartons, Pieces, Foobar" _ &"FROM Invoice where invoice_no = '" & _ Me.ComboBox5.SelectedItem.ToString.Trim &"' And category = '" & _ Me.ListBox1.SelectedItem.ToString.Trim &"' And item_name = '" & _ Me.ComboBox2.SelectedValue.ToString.Trim &"' And expiry_date = '" & _ Me.expiry.Text &"'", con) |
除其他之外,此代码并不期望用户可能没有在一个或多个UI控件中选择某些内容。
补救方法好的。
在使用之前验证数据(也使用
1 2 3 4 5 6 7 8 9 10 | Dim expiry As DateTime ' for text date validation If (ComboBox5.SelectedItems.Count > 0) AndAlso (ListBox1.SelectedItems.Count > 0) AndAlso (ComboBox2.SelectedItems.Count > 0) AndAlso (DateTime.TryParse(expiry.Text, expiry) Then '... do stuff Else MessageBox.Show(...error message...) End If |
或者,您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 | Public Class Form1 Private NameBoxes = New TextBox(5) {Controls("TextBox1"), _ Controls("TextBox2"), Controls("TextBox3"), _ Controls("TextBox4"), Controls("TextBox5"), _ Controls("TextBox6")} ' same thing in a different format: Private boxList As New List(Of TextBox) From {TextBox1, TextBox2, TextBox3 ...} ' Immediate NRE: Private somevar As String = Me.Controls("TextBox1").Text |
这是获得NRE的一种相当常见的方法。在C中,根据编码方式,IDE将报告当前上下文中不存在
无法以这种方式初始化数组和集合。此初始化代码将在构造函数创建
- 列表和集合将只是空的
- 数组将包含五个零元素
somevar 转让将导致立即的NRE,因为没有任何东西不具有.Text 属性。
稍后引用数组元素将导致nre。如果您在
由于您的
1 2 3 4 5 6 7 | Sub Form_Load(..._ '... Dim name As String = NameBoxes(2).Text ' NRE ' ... ' More code (which will likely not be executed) ' ... End Sub |
注:这适用于任何和所有控制和组件引用,使得这些引用在以下情况下是非法的:好的。
1 2 3 4 5 | Public Class Form1 Private myFiles() As String = Me.OpenFileDialog1.FileName & ... Private dbcon As String = OpenFileDialog1.FileName &";Jet Oledb..." Private studentName As String = TextBox13.Text |
部分补救好的。
奇怪的是,vb没有提供警告,但是补救方法是在表单级别声明容器,但是当控件确实存在时,在表单加载事件处理程序中初始化它们。这可以在
1 2 3 4 5 6 7 8 9 | ' Module level declaration Private NameBoxes as TextBox() Private studentName As String ' Form Load, Form Shown or Sub New: ' ' Using the OP's approach (illegal using OPTION STRICT) NameBoxes = New TextBox() {Me.Controls("TextBox1"), Me.Controls("TestBox2"), ...) studentName = TextBox32.Text ' For simple control references |
数组代码可能还没有脱离危险。在容器控件(如
既然你知道自己在寻找什么,就应该很容易找到:好的。
"button2"位于
补救方法好的。
不要使用表单的
1 2 3 4 5 6 7 8 9 10 11 | ' Declaration Private NameBoxes As TextBox() ' Initialization - simple and easy to read, hard to botch: NameBoxes = New TextBox() {TextBox1, TextBox2, ...) ' Initialize a List NamesList = New List(Of TextBox)({TextBox1, TextBox2, TextBox3...}) ' or NamesList = New List(Of TextBox) NamesList.AddRange({TextBox1, TextBox2, TextBox3...}) |
函数不返回任何内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Private bars As New List(Of Bars) ' Declared and created Public Function BarList() As List(Of Bars) bars.Clear If someCondition Then For n As Integer = 0 to someValue bars.Add(GetBar(n)) Next n Else Exit Function End If Return bars End Function |
在这种情况下,IDE将警告您"并非所有路径都返回值,可能会导致
1 2 3 | bList = myFoo.BarList() For Each b As Bar in bList ' EXCEPTION ... |
补救方法好的。
将函数中的
1 2 | bList = myFoo.BarList() If bList IsNot Nothing Then... |
执行不当的尝试/捕获
实施不当的Try/Catch可以隐藏问题所在并导致新问题出现:好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | Dim dr As SqlDataReader Try Dim lnk As LinkButton = TryCast(sender, LinkButton) Dim gr As GridViewRow = DirectCast(lnk.NamingContainer, GridViewRow) Dim eid As String = GridView1.DataKeys(gr.RowIndex).Value.ToString() ViewState("username") = eid sqlQry ="select FirstName, Surname, DepartmentName, ExtensionName, jobTitle, Pager, mailaddress, from employees1 where username='" & eid &"'" If connection.State <> ConnectionState.Open Then connection.Open() End If command = New SqlCommand(sqlQry, connection) 'More code fooing and barring dr = command.ExecuteReader() If dr.Read() Then lblFirstName.Text = Convert.ToString(dr("FirstName")) ... End If mpe.Show() Catch Finally command.Dispose() dr.Close() ' <-- NRE connection.Close() End Try |
这是一个对象没有按预期创建的情况,但也显示了空
SQL中有一个额外的逗号(在"mailaddress"之后),这会导致
一个空的
补救方法好的。
不要使用空的Try/Catch块-让代码崩溃,这样您就可以a)确定原因b)确定位置c)应用适当的补救措施。Try/Catch块并不是为了向唯一有资格修复异常的人(开发人员)隐藏异常。好的。dbnull与Nothing不同
1 2 3 | For Each row As DataGridViewRow In dgvPlanning.Rows If Not IsDBNull(row.Cells(0).Value) Then ... |
The System.DBNull value indicates that the Object represents missing or non-existent data. DBNull is not the same as Nothing, which indicates that a variable has not yet been initialized.
Ok.
补救方法好的。
1 | If row.Cells(0) IsNot Nothing Then ... |
如前所述,您可以不测试任何内容,然后测试特定值:好的。
1 | If (row.Cells(0) IsNot Nothing) AndAlso (IsDBNull(row.Cells(0).Value) = False) Then |
例2好的。
1 2 3 4 5 6 7 8 9 | Dim getFoo = (From f In dbContext.FooBars Where f.something = something Select f).FirstOrDefault If Not IsDBNull(getFoo) Then If IsDBNull(getFoo.user_id) Then txtFirst.Text = getFoo.first_name Else ... |
1 | If getFoo IsNot Nothing Then... |
控制
1 2 3 4 5 6 | Dim chk As CheckBox chk = CType(Me.Controls(chkName), CheckBox) If chk.Checked Then Return chk End If |
如果找不到带有
补救方法好的。
1 |
数据报视图
DGV有一些周期性的怪癖:好的。
1 2 3 4 5 | dgvBooks.DataSource = loan.Books dgvBooks.Columns("ISBN").Visible = True ' NullReferenceException dgvBooks.Columns("Title").DefaultCellStyle.Format ="C" dgvBooks.Columns("Author").DefaultCellStyle.Format ="C" dgvBooks.Columns("Price").DefaultCellStyle.Format ="C" |
如果
补救方法好的。
手动命名列,或按索引引用:好的。
1 | dgvBooks.Columns(0).Visible = True |
例2-小心纽罗
1 2 3 4 5 6 7 8 9 10 | xlWorkSheet = xlWorkBook.Sheets("sheet1") For i = 0 To myDGV.RowCount - 1 For j = 0 To myDGV.ColumnCount - 1 For k As Integer = 1 To myDGV.Columns.Count xlWorkSheet.Cells(1, k) = myDGV.Columns(k - 1).HeaderText xlWorkSheet.Cells(i + 2, j + 1) = myDGV(j, i).Value.ToString() Next Next Next |
当EDOCX1 21的EDCOX1,22,EDCOX1,23,(默认),在底部的空白/新行中的EDCOX1×24,都包含EDCOX1×13。大多数使用内容的尝试(例如,
补救方法好的。
使用
1 2 3 | For Each r As DataGridViewRow in myDGV.Rows If r.IsNewRow = False Then ' ok to use this row |
如果确实使用了
在某些情况下,尝试使用
1 | My.Settings.FooBars.Add("ziggy") ' foobars is a string collection |
因为vb正在为您管理设置,所以期望它初始化集合是合理的。它将,但仅当您以前(在设置编辑器中)向集合中添加了初始条目时。由于集合在添加项时(显然)已初始化,因此当设置编辑器中没有要添加的项时,它将保持
补救方法好的。
如果需要,初始化窗体的
1 2 3 |
通常,只需要在应用程序第一次运行时初始化
你可能忘记了
或好的。
您认为可以完美地执行某些操作以将已初始化的对象返回到代码中,但事实并非如此。好的。
不要忽略编译器警告(永远)并使用
msdn nullreference异常好的。好啊。
另一种情况是将空对象强制转换为值类型。例如,下面的代码:
1 2 | object o = null; DateTime d = (DateTime)o; |
它会把一个
其中一个例子是这个简单的带有日历控件的ASP.NET绑定片段:
1 | " /> |
这里,
这意味着所讨论的变量没有指向任何对象。我可以这样生成:
1 2 | SqlConnection connection = null; connection.Open(); |
这将抛出错误,因为虽然我声明了变量"
要避免此错误:
JetBrains的Resharper工具将识别代码中可能出现空引用错误的每个地方,允许您进行空检查。这个错误是第一个错误源,imho。
这意味着您的代码使用了一个设置为空的对象引用变量(即它没有引用实际的对象实例)。
为了防止出现错误,应该在使用之前测试可能为空的对象是否为空。
1 2 3 4 5 6 7 8 9 10 11 | if (myvar != null) { // Go ahead and use myvar myvar.property = ... } else { // Whoops! myvar is null and cannot be used without first // assigning it to an instance reference // Attempting to use myvar here will result in NullReferenceException } |
请注意,无论在何种情况下,.NET中的原因始终相同:
You are trying to use a reference variable whose value is
Nothing /null . When the value isNothing /null for the reference variable, that means it is not actually holding a reference to an instance of any object that exists on the heap.You either never assigned something to the variable, never created an instance of the value assigned to the variable, or you set the variable equal to
Nothing /null manually, or you called a function that set the variable toNothing /null for you.
引发这个异常的一个例子是:当您试图检查某个东西时,它是空的。
例如:
1 2 3 4 5 6 | 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相比,如果一个方法期望传递给它的内容不是空的,则通常将其作为防御措施抛出。
更多信息位于C NullReferenceException和空参数中。
如果尚未初始化引用类型,并且希望设置或读取其属性之一,则它将引发NullReferenceException。
例子:
1 2 | Person p = null; p.Name ="Harry"; // NullReferenceException occurs here. |
您可以通过检查变量是否不为空来避免这种情况:
1 2 3 4 5 | Person p = null; if (p!=null) { p.Name ="Harry"; // Not going to run to this point } |
为了完全理解引发NullReferenceException的原因,了解值类型和引用类型之间的区别是很重要的。
因此,如果您处理的是值类型,则不能发生NullReferenceExceptions。尽管在处理引用类型时需要保持警惕!
只有引用类型(顾名思义)可以保存引用或直接指向任何对象(或"空")。而值类型总是包含一个值。
引用类型(必须选中这些类型):
- 动态
- 对象
- 一串
值类型(您可以忽略这些类型):
- 数值类型
- 积分类型
- 浮点类型
- 十进制的
- 布尔
- 用户定义的结构
另一个可能发生
1 2 3 4 5 6 7 8 9 | class Book { public string Name { get; set; } } class Car { } Car mycar = new Car(); Book mybook = mycar as Book; // Incompatible conversion --> mybook = null Console.WriteLine(mybook.Name); // NullReferenceException |
这里,
一般来说,您应该使用cast或
如果您希望类型转换始终成功(即您知道对象应该提前完成),那么应该使用强制转换:
1 | ComicBook cb = (ComicBook)specificBook; |
如果您不确定类型,但希望尝试将其用作特定类型,则使用
1 2 3 4 | ComicBook cb = specificBook as ComicBook; if (cb != null) { // ... } |
您正在使用包含空值引用的对象。所以它给出了一个空异常。在该示例中,字符串值为空,当检查其长度时,发生异常。
例子:
1 2 3 4 5 | string value = null; if (value.Length == 0) // <-- Causes exception { Console.WriteLine(value); // <-- Never reached } |
异常错误为:
Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance
of an object. at Program.Main()
While what causes a NullReferenceExceptions and approaches to avoid/fix such an exception have been addressed in other answers, what many programmers haven't learned yet is how to independently debug such exceptions during development.
In Visual Studio this is usually easy thanks to the Visual Studio Debugger.
First, make sure that the correct error is going to be caught - see
How do I allow breaking on 'System.NullReferenceException' in VS2010? Note1
Then either Start with Debugging (F5) or Attach [the VS Debugger] to Running Process. On occasion it may be useful to use
Now, when the NullReferenceException is thrown (or unhandled) the debugger will stop (remember the rule set above?) on the line on which the exception occurred. Sometimes the error will be easy to spot.
For instance,
in the following line the only code that can cause the exception is if
1 | var x = myString.Trim(); |
在更高级的情况下,例如下面的情况,您需要使用上面的技术之一(监视或即时窗口)来检查表达式,以确定
1 | var x = str1.Trim() + str2.Trim(); |
一旦找到异常被抛出的位置,通常向后推理以找出引入的空值[不正确]的位置是很简单的。--
花时间了解异常的原因。检查是否有空表达式。检查以前可能导致此类空表达式的表达式。根据需要添加断点并单步执行程序。使用调试器。
1如果中断引发的攻击性太强,并且调试器在.NET或第三方库中的NPE上停止,则可以使用未处理的中断用户来限制捕获的异常。此外,VS2012只引入了我的代码,我建议启用它。
If you are debugging with Just My Code enabled, the behavior is slightly different. With Just My Code enabled, the debugger ignores first-chance common language runtime (CLR) exceptions that are thrown outside of My Code and do not pass through My Code
西蒙:mourier给这个exampleP></
1 2 | object o = null; DateTime d = (DateTime)o; // NullReferenceException |
在拆箱转换从安(铸造)(or from one of the
在the other direction,节礼
1 2 3 | DateTime? d = null; var s = d.ToString(); // OK, no exception (no boxing), returns"" var t = d.GetType(); // Bang! d is boxed, NullReferenceException |
有时发生在一节礼茶的方式。for example with this GENERIC:非扩展方法P></
1 2 3 4 | public static void MyExtension(this object x) { x.ToString(); } |
problematic will be the following队列:P></
1 2 | DateTime? d = null; d.MyExtension(); // Leads to boxing, NullReferenceException occurs inside the body of the called method, not here. |
这些案例arise because of the special rules when the uses拳击
当实体框架中使用的实体的类名与Web表单代码隐藏文件的类名相同时,添加一个事例。
假设您有一个web表单contact.aspx,其代码隐藏类是contact,并且您有一个实体名contact。
然后在调用Context.SaveChanges()时,以下代码将引发NullReferenceException。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | Contact contact = new Contact { Name ="Abhinav <hr><P>另一个可能收到这个异常的一般情况是在单元测试期间模拟类。无论使用的是模拟框架,都必须确保类层次结构的所有适当级别都被正确模拟。尤其是,被测试代码引用的<wyn>HttpContext</wyn>的所有属性都必须被模拟。</P><P>请参阅"测试自定义authorizationalattribute时引发的nullreferenceexception",以获取一些详细的示例。</P><p><center>[wp_ad_camp_3]</center></p><hr><P>我在不同的角度answering to this。this sort of answers"什么人能把avoid恩?"P></<P>当工作在不同的层中,for example安MVC应用到呼叫控制器服务,在业务运营的需要。在这样的场景依赖注入容器can be used to the to the初始化服务avoid NullReferenceException。我知道你不need to that means for零只是担心检查服务和呼叫控制器as the from the available to(虽然他们将永远与initialized)在AS或prototype或者单身。P></[cc lang="csharp"]public class MyController { private ServiceA serviceA; private ServiceB serviceB; public MyController(ServiceA serviceA, ServiceB serviceB) { this.serviceA = serviceA; this.serviceB = serviceB; } public void MyMethod() { // We don't need to check null because the dependency injection container // injects it, provided you took care of bootstrapping it. var someObject = serviceA.DoThis(); } } |
of on the物"。要给什么,there can be many"的答案。P></
更"正规"的方式这样的条件而开发preventing of error is求职模式的合同设计在你的尾巴。You need to this均值集类的不变量,和/或偶函数/方法preconditions在线你和后置条件系统,同时开发。P></
总之,类不变量约束确保that there will be some that will not get在你的类中使用violated(正规和therefore Will not get the class,在安inconsistent了)。preconditions given as to that日期输入均值函数必须在后续的一些约束集法/永远不侵犯他们,和后置条件均值函数/方法,后续输出必备茶具又没有过约束violating them。合同的条件不好violated should of a无缺陷在执行程序,therefore设计模式在实践中checked contract is disabled在调试模式,而被释放,maximize to the自主开发的系统的性能。P></
这样,你可以avoid
1 2 3 4 5 6 | public X { get; set; } public void InvokeX() { X.DoSomething(); // if X value is null, you will get a NullReferenceException } |
"但如果你不必须有属性集X为null值,那么"As You can防止precondition method,the before情景描述的程序办理:P></
1 2 3 4 5 6 7 | //Using code contracts: [ContractInvariantMethod] protected void ObjectInvariant () { Contract.Invariant ( X != null ); //... } |
for this code for原因,合同项目名称出现的应用程序。P></
alternatively设计模式的应用,可以使用assertions合同。P></
更新:is that the term was值得提coined connection with by梅耶尔在他的规划设计of the Eiffel语言。P></
当我们是扔在
for example:P></
当method of an empty string字符串accessed:P></
1 2 | string str = string.Empty; str.ToLower(); // throw null reference exception |
when a property of a null对象:accessedP></
1 2 3 4 5 | Public Class Person { public string Name { get; set; } } Person objPerson; objPerson.Name /// throw Null refernce Exception |
tl;dr:尝试使用
当我试图通过发送一个模型来呈现一个视图中的视图时,我得到了
1 2 3 4 | @{ MyEntity M = new MyEntity(); } @RenderPage("_MyOtherView.cshtml", M); // error in _MyOtherView, the Model was Null |
调试显示myotherview中的模型为空。直到我把它改成:
1 2 3 4 |
它奏效了。
此外,我没有开始使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @inherits System.Web.Mvc.WebViewPage @{ ViewBag.Title ="Entity Index"; List<MyEntity> MyEntities = new List<MyEntity>(); MyEntities.Add(new MyEntity()); MyEntities.Add(new MyEntity()); MyEntities.Add(new MyEntity()); } @{ foreach(var M in MyEntities) { // Squiggly lines below. Hovering says: cannot convert method group 'partial' to non-delegate type Object, did you intend to envoke the Method? @Html.Partial("MyOtherView.cshtml"); } } |
但是我可以运行应用程序,而不必担心这个"错误"。我可以通过改变
1 2 3 | @foreach(var M in MyEntities){ ... } |
虽然我有一种感觉,那是因为Visual Studio误读了符号和括号。
你能怎么办?
这里有很多很好的答案来解释什么是空引用以及如何调试它。但是,关于如何防止这个问题,或者至少让它更容易被抓住的问题,却很少。
检验参数
例如,方法可以检查不同的参数以查看它们是否为空,并抛出一个
1 2 3 4 5 6 | public void DoSomething(MyObject obj) { if(obj == null) { throw new ArgumentNullException("obj","Need a reference to obj."); } } |
使用工具
还有几个图书馆可以提供帮助。"例如,"resharper"可以在编写代码时向您提供警告,特别是当您使用它们的属性:notNullAttribute时。
在"微软代码契约"中,你使用像
还有"postsharp",允许您使用如下属性:
1 | public void DoSometing([NotNull] obj) |
通过这样做并使postsharp成为构建过程的一部分,将在运行时检查
纯代码解决方案
或者,您可以使用简单的旧代码编写自己的方法。例如,这里有一个结构,您可以使用它来捕获空引用。它是根据与
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | [System.Diagnostics.DebuggerNonUserCode] public struct NotNull<T> where T: class { private T _value; public T Value { get { if (_value == null) { throw new Exception("null value not allowed"); } return _value; } set { if (value == null) { throw new Exception("null value not allowed."); } _value = value; } } public static implicit operator T(NotNull<T> notNullValue) { return notNullValue.Value; } public static implicit operator NotNull<T>(T value) { return new NotNull<T> { Value = value }; } } |
你将使用与你使用
1 2 3 | NotNull<Person> person = null; // throws exception NotNull<Person> person = new Person(); // OK NotNull<Person> person = GetPerson(); // throws exception if GetPerson() returns null |
1 2 3 4 5 6 7 | Person person = new Person { Name ="John" }; WriteName(person); public static void WriteName(NotNull<Person> person) { Console.WriteLine(person.Value.Name); } |
正如您在上面看到的那样,对于nullable,您可以通过
1 2 3 4 5 6 | Person person = GetPerson(); public static NotNull<Person> GetPerson() { return new Person { Name ="John" }; } |
或者您甚至可以在方法通过执行强制转换返回
1 2 3 4 5 6 | Person person = (NotNull<Person>)GetPerson(); public static Person GetPerson() { return new Person { Name ="John" }; } |
与分机结合
将
1 2 3 4 5 6 7 8 9 10 11 12 13 | [System.Diagnostics.DebuggerNonUserCode] public static class NotNullExtension { public static T NotNull<T>(this T @this) where T: class { if (@this == null) { throw new Exception("null value not allowed"); } return @this; } } |
下面是一个如何使用它的示例:
1 | var person = GetPerson().NotNull(); |
github
为了供您参考,我在Github上提供了上述代码,您可以在以下网址找到:
https://github.com/luisperezphd/not空
相关语言功能
C 6.0引入了"空条件运算符",这有一点帮助。使用此功能,可以引用嵌套对象,如果其中任何一个对象是
这减少了在某些情况下必须执行的空检查的数量。语法是在每个点前面加一个问号。以下面的代码为例:
1 | var address = country?.State?.County?.City; |
假设
这是一个很好的功能,但它提供的信息较少。这并不能说明4个中的哪个是空的。
像nullable一样内置?
C有一个很好的
如果C有类似于上面的
您可以使用C 6中的空条件运算符以干净的方式修复nullreferenceexception,并编写更少的代码来处理空检查。
它用于在执行成员访问(?)或指数(?[手术]。
例子
1 | var name = p?.Spouse?.FirstName; |
相当于:
1 2 3 4 5 6 7 | if (p != null) { if (p.Spouse != null) { name = p.Spouse.FirstName; } } |
结果是,当p为空或p.配偶为空时,名称将为空。
否则,变量名将被指定为p.spouse.firstname的值。
有关详细信息:空条件运算符
错误行"对象引用未设置为对象的实例。"表示尚未将实例对象分配给对象引用,但仍在访问该对象的属性/方法。
例如:假设您有一个名为MyClass的类,它包含一个属性prop1。
1 2 3 4 | public Class myClass { public int prop1 {get;set;} } |
现在您可以在其他类中访问这个prop1,如下所示:
1 2 3 4 5 6 7 8 | public class Demo { public void testMethod() { myClass ref = null; ref.prop1 = 1; //This line throws error } } |
上面的行引发错误,因为类MyClass的引用已声明但未实例化,或者对象的实例未分配给该类的referecne。
要解决这个问题,必须实例化(将对象赋给该类的引用)。
1 2 3 4 5 6 7 8 9 | public class Demo { public void testMethod() { myClass ref = null; ref = new myClass(); ref.prop1 = 1; } } |
有趣的是,本页的答案中没有一个提到两个边缘案例,如果我添加它们,希望没有人介意:
边缘大小写1:同时访问字典.NET中的通用字典不是线程安全的,当您试图从两个并发线程访问密钥时,它们有时可能会抛出一个
如果
(另外一个不使用不安全代码的原因,除非您需要,顺便说一下)
NullReferenceException或未设置为对象实例的对象引用在未实例化您尝试使用的类的对象时发生。例如:
假设您有一个名为student的班级。
1 2 3 4 5 6 7 8 9 | public class Student { private string FirstName; private string LastName; public string GetFullName() { return FirstName + LastName; } } |
现在,考虑另一个班级,你正在尝试检索学生的全名。
1 2 3 4 5 6 7 8 9 | public class StudentInfo { public string GetStudentName() { Student s; string fullname = s.GetFullName(); return fullname; } } |
如上述代码所示,声明student s-仅声明student类型的变量,注意,此时未实例化student类。因此,当执行语句s.getfullname()时,它将抛出NullReferenceException。
简单来说:
您正在尝试访问一个未创建或当前不在内存中的对象。
那么如何解决这个问题:
调试并让调试程序中断…它将直接把你带到被破坏的变量…现在你的任务就是简单地解决这个问题。在适当的位置使用新的关键字。
如果是由于对象不存在而在某些数据库命令上导致的,则只需执行空检查并处理它:
1 2 3 | if (i == null) { // Handle this } |
最难的……如果GC已经收集了对象…如果您试图使用字符串查找对象,通常会发生这种情况…也就是说,通过对象的名称找到它,那么GC可能已经清理了它…这很难找到,而且将成为一个相当大的问题…解决这个问题的一个更好的方法是在开发过程中,在任何必要的地方执行空检查。这会节省你很多时间。
通过按名称查找,我的意思是一些框架允许您使用字符串查找对象,代码可能如下所示:findobject("objectname");
如果我们考虑可以抛出此异常的常见场景,那么可以使用顶部的对象访问属性。
前任:
1 2 | string postalcode=Customer.Address.PostalCode; //if customer or address is null , this will through exeption |
在这里,如果地址为空,那么您将获得NullReferenceException。
因此,作为一种实践,在访问这些对象(特别是通用对象)中的属性之前,我们应该始终使用空检查。
1 2 | string postalcode=Customer?.Address?.PostalCode; //if customer or address is null , this will return null, without through a exception |
从字面上来说,修复nullreferenceexection的最简单方法有两种。如果你有一个游戏对象,例如一个附加了脚本和一个名为rb(rigidbody)的变量,这个变量在你开始游戏时将以空开始。这就是为什么您得到一个nullreferenceexection的原因,因为计算机没有存储在该变量中的数据。
我将使用一个刚体变量作为例子。实际上,我们可以通过以下几种方式轻松添加数据:
进一步说明:如果希望Unity向对象添加组件,而您可能忘记添加组件,则可以在类声明上方(所有using下方的空格)键入
如果在保存或编译生成期间收到此消息,只需关闭所有文件,然后打开任何要编译和保存的文件。
对我来说,原因是我重命名了文件,而旧文件仍然打开。
要使用对象的方法和成员,首先必须创建该对象。如果您没有创建它(应该保存对象的变量没有初始化),但是您试图使用它的方法或变量,您会得到这个错误。
有时您可能只是忘记了进行初始化。
已编辑:new不能返回空值,但失败时激发异常。很久以前,在某些语言中是这样的,但现在不是了。感谢@John Saunders指出这一点。
这基本上是一个空引用异常。如微软所说-
A NullReferenceException exception is thrown when you try to access a
member of a type whose value is null.
那是什么意思?
这意味着,如果任何一个成员不具备任何价值,而我们让该成员执行某项任务,那么系统无疑会抛出一条消息并说-
"嘿,等等,那个成员没有值,所以它不能执行您要交付的任务。"
异常本身表示正在引用某些内容,但未设置其值。因此,这表示它只在使用引用类型作为值类型不可为空时发生。
如果使用值类型成员,则不会发生NullReferenceException。
1 2 3 4 5 6 7 8 9 | class Program { static void Main(string[] args) { string str = null; Console.WriteLine(str.Length); Console.ReadLine(); } } |
上面的代码显示了一个简单的字符串,它被赋予了一个空值。
现在,当我尝试打印字符串str的长度时,我确实得到一个未处理的类型为"System.NullReferenceException"的异常,因为成员str指向空,并且不能有任何长度的空值。
当我们忘记实例化引用类型时,也会发生"NullReferenceException"。
假设我在其中有一个类和成员方法。我没有实例化我的类,但只命名了我的类。现在,如果我尝试使用该方法,编译器将抛出错误或发出警告(取决于编译器)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class Program { static void Main(string[] args) { MyClass1 obj; obj.foo(); //Use of unassigned local variable 'obj' } } public class MyClass1 { internal void foo() { Console.WriteLine("hello from foo"); } } |
上述代码的编译器会引发一个错误,即变量obj未赋值,这表示变量的值为空或为零。上述代码的编译器会引发一个错误,即变量obj未赋值,这表示变量的值为空或为零。
为什么会发生?NullReferenceException是由于我们不检查对象值的错误而产生的。我们经常在代码开发中不选中对象值。
当我们忘记实例化对象时,它也会出现。使用可以返回或设置空值的方法、属性、集合等也可能是导致此异常的原因。
怎样才能避免呢?
有各种方法和方法可以避免这种著名的例外:
显式检查:我们应该遵循检查对象、属性、方法、数组和集合是否为空的传统。这可以简单地使用条件语句实现,如if else if else等。
异常处理:管理此异常的重要方法之一。使用简单的try catch finally块,我们可以控制这个异常并维护它的日志。当应用程序处于生产阶段时,这非常有用。
空运算符:空合并运算符和空条件运算符在设置对象、变量、属性和字段的值时也很方便。
调试器:对于开发人员来说,我们拥有调试的强大武器。如果在开发过程中我们面对nullreferenceexception,我们可以使用调试器来获取异常的源。
内置方法:系统方法(如getValueOrDefault()、isNullOrWhiteSpace()和isNullOrEmpty())检查空值,如果有空值,则分配默认值。
这里已经有很多好的答案了。你也可以通过我博客上的例子来查看更详细的描述。
希望这也有帮助!
You are trying to access an object that isn't created or currently not in memory.
当我得到这个错误时,我将以下代码添加到任何触发该错误的事件处理程序中。
1 | if (!IsLoaded) return; |
这个!意思是"不",仅供参考。因此,如果没有加载相关对象,程序将终止执行并防止崩溃。
可能会发生与类相关的场景。在我陈述解决方案之前,这个问题就结束了:https://stackoverflow.com/questions/43348009/unable-to-instantation-class
注意不要实例化类:如果类中的构造函数的任何部分抛出了
我实例化了一个类:
1 2 |
在类内部是一个从
如果您曾经遇到过类不实例化的情况,请尝试确保类构造函数的任何部分都不会抛出