VB.Net 2010 使用列表作为值从 Dictionary 声明变量时,“对象引用未设置为对象的实例”

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

提问人:BrightBulb123 提问时间:7/20/2021 最后编辑:BrightBulb123 更新时间:8/9/2021 访问量:226

问:

这是一个编程的学校项目(不是评估或作业,所以我不是在作弊),我必须制作一个 7 段显示源 1。我决定不走传统方式,手动将每个按钮设置为可见,按下每个按钮以显示一个数字;将相应的数字和要打开的数字作为键值对存储在字典中。我对 Python 有一些了解,所以这就是我的想法。我的表单源 2 有 7 个 (s) 和 10 个 (s)。就像一个实验,因为这是我第一次使用和参与,我决定现在只尝试一下这个数字(并且应该是可见的)。这是我制作的字典:RectangeShapeRectangleShapeRectangleShapeButtonDictionariesListsVB.net1shp4shp5

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 = TrueNullReferenceExceptionObject reference not set to an instance of an object.

来源

来源 1:

Image of a 7-Segment Display来源 2:

My 7-Segment Display Visual Basic Form

vb.net 列表 字典 nullreferenceexception vb.net-2010

评论

1赞 jmcilhinney 7/20/2021
首先,为什么要使用数组而不是数组?是否需要添加或删除项目?我不认为,所以 a 与数组相比没有任何优势,但它确实包括开销。您应该在合适的位置使用数组,在它们不合适的位置使用集合。ListsList
1赞 jmcilhinney 7/20/2021
我还倾向于建议使用 GDI+ 来绘制段,而不是使用 .由于某种原因,不再支持 PowerPack。Shapes

答:

1赞 jmcilhinney 7/20/2021 #1

编程不是魔术。它的工作方式与您预期的差不多。如果你要摆脱你的内心,那么你必须投入。在发布之前是否使用过调试器?当执行此行时,您是否实际查看了 等的值:NothingListDictionaryNothingshp2

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}}}

根据您在第二个代码段中对该变量的使用,它必须是成员变量,这意味着第一个代码段位于任何方法之外,这意味着它在类构造函数之前执行,这意味着当时尚未创建任何控件,这意味着引用控件的任何字段都只能是 。如果你在该行上放置了一个断点,并使用了调试器,那么你就会看到这一点。NumbersNothing

解决方案是在创建它们之前,不会实际将 添加到集合中。这意味着在调用 .这意味着您可以创建自己的构造函数,并根据需要在那里执行,但您可能应该只在事件处理程序中执行。只需声明变量而不创建对象:ShapesInitializeComponentLoadDictionary

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

评论

0赞 BrightBulb123 7/20/2021
我对数组一无所知,因为我们还没有了解它们。但感谢您的回答和时间。是的,问题在于我在表单实际初始化所有组件之前声明并赋予变量值。我把它改成了你说的,现在已经在 中声明了它,但是在事件处理程序中为它分配了一个值,它现在可以工作了。再次感谢您的帮助。NumbersPublic Classload
1赞 jmcilhinney 7/20/2021
无论你参加什么课程/课程,你都有点失败,因为你在像数组这样基本的东西之前就已经了解了复杂的集合。A 基本上是一个动态数组,即您以相同的方式按索引获取和设置项目,但集合将随着您添加和删除项目而增长和缩小,其中数组是固定大小的。实际上,它在内部维护一个数组,并增加了一层复杂性来实现这种动态行为。如果不需要行为,则不应增加复杂性。在这种情况下,数组对你来说并不难用。ListList
0赞 BrightBulb123 7/20/2021
至于调试器,我没有那么多经验,所以我真的不知道该怎么做。我知道这看起来很愚蠢。如果我的帖子让人觉得我直接跳起来问这个问题,不;在问这个问题之前,我做了很多谷歌搜索了大约半个小时。但我现在明白了,如果 oyu 对此感到沮丧。我也知道编程不是魔术,但只要忘记一件简单的事情,比如检查调试器,就会让它看起来如此。如果这篇文章以任何方式激怒了您,我很抱歉,但我非常感谢您提供的提示和帮助。谢谢。VB.net
1赞 BrightBulb123 7/20/2021
这是10年级的高中班。我们还没有学到任何这些,我只是想做一些事情,而不是为表单上的每个按钮写出 100 行代码。我希望你能理解。
0赞 BrightBulb123 7/20/2021
我现在还将研究数组。谢谢你的建议!
1赞 user16594857 8/8/2021 #2

在您的 7 段显示表单上,我将使用一个包含为每个字典键(数字)打开的矩形。这需要首先以编程方式将 7 个形状添加到表单上(看起来您已经对其进行了编码),然后在每个按钮(用于数字)中选择打开的矩形并更改其背景颜色。可能没有必要将所有形状(矩形)“前置”到字典中,因为它们已经手动固定在表单上。如果不是,则拉出将它们放在窗体上的代码,并在窗体加载时首先运行一次。使用这种方法,您不必再担心形状。List (of String)

在表格 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

最后,在数字 1 的按钮_Click中,使用以下命令:

'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