VB.Net 2010 "Object reference not set to an instance of an object." 以列表作为值从字典声明变量时
VB.Net 2010 "Object reference not set to an instance of an object." when declaring a variable from a Dictionary with a list as the value
这是一个学校的编程项目(不是评估或作业,所以我没有作弊),我必须在其中制作 7 段显示来源 1。我决定不采用传统方式,而是手动将每个 RectangeShape
设置为在按下的每个按钮上可见以显示数字;将相应的数字和要打开的 RectangleShape
(s) 作为键值对存储在字典中。我对 Python 有一些了解,所以这就是我的灵感来源。我的表格 Source 2 有 7 RectangleShape
(s) 和 10 Button
(s)。作为一个实验,因为这是我第一次在 VB.net
中使用 Dictionaries
和 Lists
,我决定暂时只对数字 1
进行尝试(shp4
和 shp5
应该是可见的)。这是我制作的词典:
Dim Numbers As New Dictionary(Of Integer, List(Of PowerPacks.Shape)) From {{1, New List(Of PowerPacks.Shape) From {shp4, shp5}}, {2, New List(Of PowerPacks.Shape) From {shp2, shp3}}}
这是按钮 (btn1
) 的代码:
Private Sub btn1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn1.Click
Dim Thing As PowerPacks.Shape = Numbers(1)(0)
Thing.Visible = True
End Sub
当程序到达 Thing.Visible = True
行时,它会抛出一个错误。这是一个 NullReferenceException
声明 Object reference not set to an instance of an object.
关于如何解决这个问题的任何想法?
来源
来源 1:
来源 2:
编程不是魔法。它的工作原理与您预期的差不多。如果您在 Dictionary
中从 List
中获取 Nothing
,那么您必须将 Nothing
放入。您在发布之前是否使用了调试器?当这一行被执行时,你真的看过 shp2
等的值吗:
Dim Numbers As New Dictionary(Of Integer, List(Of PowerPacks.Shape)) From {{1, New List(Of PowerPacks.Shape) From {shp4, shp5}}, {2, New List(Of PowerPacks.Shape) From {shp2, shp3}}}
根据你在第二个代码片段中使用那个 Numbers
变量,它必须是一个成员变量,这意味着第一个代码片段在任何方法之外,这意味着它在class 构造函数,这意味着此时还没有创建控件,这意味着任何引用控件的字段只能是Nothing
。如果您在该行上放置了一个断点并使用了调试器,那么您应该已经看到了。
解决方案是在创建 Shapes
之前将它们实际添加到集合中。这意味着在调用 InitializeComponent
之后。这意味着您可以创建自己的构造函数并根据需要在那里执行,但您可能应该只在 Load
事件处理程序中执行。只需声明 Dictionary
变量而不创建对象:
Private numbers As Dictionary(Of Integer, PowerPacks.Shape())
请注意,我提供了一个显式访问修饰符,您应该始终对所有成员执行此操作,并且还以小写字母开头的名称,您可能应该对所有私有字段执行此操作。然后在 load
事件处理程序中创建对象:
numbers As New Dictionary(Of Integer, PowerPacks.Shape()) From {{1, {shp4, shp5}},
{2, {shp2, shp3}}}
我冒昧地使用数组而不是 Lists
来简化它,因为它没有任何价值。
在您的 7 段显示表单中,我会使用一个 List (of String)
,其中包含为每个字典键(数字)打开的矩形。这将需要首先以编程方式将 7 个形状添加到表单上(看起来您已经编写了代码),然后在每个按钮(对于数字)中只需选择打开的矩形并更改它们的背景颜色。将所有形状(矩形)“前端加载”到字典中可能是不必要的,因为它们已经手动固定在表单上。如果不是,则提取将它们放在表单上的代码,然后 运行 第一次,一次,当表单加载时。使用这种方法,您不必再担心形状问题。
在表格 1 中,添加:
Dim dicRSBackColor As New Dictionary(Of Integer, List(Of String))
Dim SC As New ShapeContainer
在Form1_Load中添加以下内容:
'define each of the 7 rectangles using, e.g.:
Dim myrec4 As New RectangleShape
myrec4.Name = "shp4"
myrec4.Visible = True
myrec4.BringToFront()
'add locations and size to myrec4
myrec4.Top=100
myrec4.Left=100
myrec4.Width=10
myrec4.Height=100
'then add myrec4 to Shape container
SC.Shapes.Add(myrec4)
'add myrec4 to Form1
Me.Controls.Add(myrec4)
'do the above for all 7 rectangleshapes
'For the dictionary, add number 1's rectangleshape (turned on)
Dim mylist As List(Of String)
mylist.Add("shp4")
mylist.Add("shp5")
dicRSBackColor.Add(1, mylist)
'add number 2 rectangles (turned on)
mylist.Clear()
mylist.Add("shp1")
mylist.Add("shp3")
mylist.Add("shp4")
mylist.Add("shp6")
mylist.Add("shp7")
dicRSBackColor.Add(2, mylist)
'continue until all 7 rec's added
最后,在按钮 _Click for number 1 中,使用以下内容:
'First change background color of all rectangleshapes to Form1's back color
For Each rs As RectangleShape In Me.SC.Shapes
rs.BackColor = Me.BackColor
Next
'Now pull the list of shapes that are turned on for number 1 using the dictionary
Dim mylist1 As List(Of String)
mylist1 = dicRSBackColor(1) 'you're pulling the value for key=1, which is a list of strings
'use a double loop and find out when the list value is the same as the name of the rectangleshape, and then set the back color to orange
For Each item In mylist1
For Each rs As RectangleShape In Me.SC.Shapes
If item = rs.Name Then rs.BackColor = Color.Orange
Next
Next
这是一个学校的编程项目(不是评估或作业,所以我没有作弊),我必须在其中制作 7 段显示来源 1。我决定不采用传统方式,而是手动将每个 RectangeShape
设置为在按下的每个按钮上可见以显示数字;将相应的数字和要打开的 RectangleShape
(s) 作为键值对存储在字典中。我对 Python 有一些了解,所以这就是我的灵感来源。我的表格 Source 2 有 7 RectangleShape
(s) 和 10 Button
(s)。作为一个实验,因为这是我第一次在 VB.net
中使用 Dictionaries
和 Lists
,我决定暂时只对数字 1
进行尝试(shp4
和 shp5
应该是可见的)。这是我制作的词典:
Dim Numbers As New Dictionary(Of Integer, List(Of PowerPacks.Shape)) From {{1, New List(Of PowerPacks.Shape) From {shp4, shp5}}, {2, New List(Of PowerPacks.Shape) From {shp2, shp3}}}
这是按钮 (btn1
) 的代码:
Private Sub btn1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn1.Click
Dim Thing As PowerPacks.Shape = Numbers(1)(0)
Thing.Visible = True
End Sub
当程序到达 Thing.Visible = True
行时,它会抛出一个错误。这是一个 NullReferenceException
声明 Object reference not set to an instance of an object.
关于如何解决这个问题的任何想法?
来源
来源 1:
来源 2:
编程不是魔法。它的工作原理与您预期的差不多。如果您在 Dictionary
中从 List
中获取 Nothing
,那么您必须将 Nothing
放入。您在发布之前是否使用了调试器?当这一行被执行时,你真的看过 shp2
等的值吗:
Dim Numbers As New Dictionary(Of Integer, List(Of PowerPacks.Shape)) From {{1, New List(Of PowerPacks.Shape) From {shp4, shp5}}, {2, New List(Of PowerPacks.Shape) From {shp2, shp3}}}
根据你在第二个代码片段中使用那个 Numbers
变量,它必须是一个成员变量,这意味着第一个代码片段在任何方法之外,这意味着它在class 构造函数,这意味着此时还没有创建控件,这意味着任何引用控件的字段只能是Nothing
。如果您在该行上放置了一个断点并使用了调试器,那么您应该已经看到了。
解决方案是在创建 Shapes
之前将它们实际添加到集合中。这意味着在调用 InitializeComponent
之后。这意味着您可以创建自己的构造函数并根据需要在那里执行,但您可能应该只在 Load
事件处理程序中执行。只需声明 Dictionary
变量而不创建对象:
Private numbers As Dictionary(Of Integer, PowerPacks.Shape())
请注意,我提供了一个显式访问修饰符,您应该始终对所有成员执行此操作,并且还以小写字母开头的名称,您可能应该对所有私有字段执行此操作。然后在 load
事件处理程序中创建对象:
numbers As New Dictionary(Of Integer, PowerPacks.Shape()) From {{1, {shp4, shp5}},
{2, {shp2, shp3}}}
我冒昧地使用数组而不是 Lists
来简化它,因为它没有任何价值。
在您的 7 段显示表单中,我会使用一个 List (of String)
,其中包含为每个字典键(数字)打开的矩形。这将需要首先以编程方式将 7 个形状添加到表单上(看起来您已经编写了代码),然后在每个按钮(对于数字)中只需选择打开的矩形并更改它们的背景颜色。将所有形状(矩形)“前端加载”到字典中可能是不必要的,因为它们已经手动固定在表单上。如果不是,则提取将它们放在表单上的代码,然后 运行 第一次,一次,当表单加载时。使用这种方法,您不必再担心形状问题。
在表格 1 中,添加:
Dim dicRSBackColor As New Dictionary(Of Integer, List(Of String))
Dim SC As New ShapeContainer
在Form1_Load中添加以下内容:
'define each of the 7 rectangles using, e.g.:
Dim myrec4 As New RectangleShape
myrec4.Name = "shp4"
myrec4.Visible = True
myrec4.BringToFront()
'add locations and size to myrec4
myrec4.Top=100
myrec4.Left=100
myrec4.Width=10
myrec4.Height=100
'then add myrec4 to Shape container
SC.Shapes.Add(myrec4)
'add myrec4 to Form1
Me.Controls.Add(myrec4)
'do the above for all 7 rectangleshapes
'For the dictionary, add number 1's rectangleshape (turned on)
Dim mylist As List(Of String)
mylist.Add("shp4")
mylist.Add("shp5")
dicRSBackColor.Add(1, mylist)
'add number 2 rectangles (turned on)
mylist.Clear()
mylist.Add("shp1")
mylist.Add("shp3")
mylist.Add("shp4")
mylist.Add("shp6")
mylist.Add("shp7")
dicRSBackColor.Add(2, mylist)
'continue until all 7 rec's added
最后,在按钮 _Click for number 1 中,使用以下内容:
'First change background color of all rectangleshapes to Form1's back color
For Each rs As RectangleShape In Me.SC.Shapes
rs.BackColor = Me.BackColor
Next
'Now pull the list of shapes that are turned on for number 1 using the dictionary
Dim mylist1 As List(Of String)
mylist1 = dicRSBackColor(1) 'you're pulling the value for key=1, which is a list of strings
'use a double loop and find out when the list value is the same as the name of the rectangleshape, and then set the back color to orange
For Each item In mylist1
For Each rs As RectangleShape In Me.SC.Shapes
If item = rs.Name Then rs.BackColor = Color.Orange
Next
Next