vb.net“For Each”仅在列表上迭代一次

时间:2013-05-16 15:36:08

标签: vb.net

以下“for each”循环仅运行一次。为什么呢?

该项目包含4个表格。 Form1包含4个PictureBox。我正在尝试迭代一个表单列表(在这个例子中,将每个表单的BG设置为图片框):

Sub Butt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Butt.Click
    Dim Forms As New List(Of Form)
    Dim Pics As New Dictionary(Of Form, PictureBox)
    Forms.Add(me)
    Forms.Add(form2)
    Forms.Add(form3)
    Forms.Add(form4)

仅执行第一次迭代:

    For Each frm As Form In Forms
        pics(frm) = Me.Controls("PictureBox" + CStr(i + 1))(0)
        'BTW the next line behave the same:
        '  pics(frm) = CType(Me.Controls("PictureBox" + CStr(i + 1)), PictureBox)
        'or this:
        '  pics(frm) = PictureBox1
        'or if the pics is a dictionary(of string):
        '  pics(frm.name) = PictureBox1
    Next

执行所有4次迭代:

    For Each frm As Form In Forms
        msgbox(frm.name)
    Next

为什么它不能在第一个循环中完成所有4次迭代?

修改

“我”不是问题。 显然问题在于将相同的控件分配两次,作为“pics”字典的值......仍在调查中。

编辑2 - 中间摘要

工作解决方案(但不是答案)

For x As Integer = 0 To Forms.Count - 1
    pics(Forms(x)) = DirectCast(PictureBox1, PictureBox)
Next

您的答案可以归为

1。字典语法:dict.add(k,v)与dict(k)= v

2。正如一些人所建议的那样,吃掉我的例外。

3。按照@Andre Pageot

的建议,需要施放伏都教

4。 VB不喜欢在字典中添加两次相同的图片框。

(1。)可能不是问题。语法 dict(k)= v 适用于其他任何地方。我甚至尝试过dict.add(k,v),它给了EXCATLY相同的行为,即仍然是错误。

(2。)IDE中确实存在问题:调试器跳过“Next”语句,并继续像往常一样循环后的下一条指令。 (WTF) 即使在我设置为在Alt + Ctrl + E屏幕中捕获所有异常后也没关系。 这个例外仍未被发现。

这是恕我直言,一个严重的错误,即使雷德蒙德的某个人设计它。同样的“搞笑行为”可能是从VB6时代继承而来的,有时候代码是“没有任何理由地”飞走了。 (但至少在那里退出了申请)。

P.S。我没有任何“try - catch”条款,也没有“错误做一些愚蠢的事情”,只是为了清楚:)

(3。)它可能是它,虽然我不明白,但它没有回答这个问题 - “为什么原始代码在运行期间正在做weewooo”。

请参阅上面的“工作解决方案”。

我真的不想理解它,因为它让我疯狂,为什么,在PYTHON,我只写dict(k)= y而且它永远不会破坏。我不理解它有可能dict.contains(k,v)。它没有任何意义。 并且必须是感觉,它是编程,而不是伏都教。

(4。)我没有任何方式(或将会)证明它。

谢谢你们。

在这个项目之后,我可能永远不会再使用VB了。有很多伏都教的事要处理,不值得头痛。

3 个答案:

答案 0 :(得分:2)

由于这一部分:

pics(frm)

可能是Nothing。我在这里猜测是因为我没有抛出这种情况。

您永远无法获得Next声明。这就是你只有一次迭代的原因。
你的错误被其他地方吞没了。尝试在异常面板中激活公共语言运行时异常 Thrown 属性。 ( ctrl + alt + e )。


也许你应该尝试替换

pics(frm)

通过

pics.Add(frm, Me.Controls("PictureBox" + CStr(i + 1))(0))

答案 1 :(得分:2)

我似乎记得遇到类似的问题,如果内存服务的技巧是客观地从每个像这样删除表单

Sub Butt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles     Butt.Click
Dim Forms As New List(Of Form)
Dim Pics As New Dictionary(Of Form, PictureBox)
Forms.Add(me)
Forms.Add(form2)
Forms.Add(form3)
Forms.Add(form4)

For x As Integer = 0 To Forms.Count - 1
    If Not Pics.Contains(Forms(x), DirectCast(Me.Controls("PictureBox" + CStr(i + 1))(0), PictureBox)) Then
            Pics.Add(Forms(x), DirectCast(Me.Controls("PictureBox" + CStr(i + 1))(0), PictureBox))
        Else
            Pics(Forms(x)) = DirectCast(Me.Controls("PictureBox" + CStr(i + 1))(0), PictureBox)
        End If
Next

<强> ############################################ ###############################################更新探索和扩展在上述############################################### ###############################

以下是对此问题的更详细解释和分解以及为什么它实际上不是.NET中的神话或奇怪

.NET OO框架非常复杂且功能强大,要理解并记住这一切并非人类不可能,但需要掌握一些概念才能在迷宫中导航。

让我们检查出现了什么问题。

您为项目中的每个表单声明并填充了表单 List(Of Form)的列表

Dim Forms as New List(Of Form)

然后你声明了一个字典来保存形状(Form,PictureBox)的(键,值)集合

Dim Pics as New Dictionary(Of Form, PictureBox)

这意味着您的“Key”是Form类型,而您的“Value”是PictureBox类型

现在,使用您在列表中的每个表单中迭代的表单列表,说明您想要“键”(表格)的“值”(PictureBox) / em>在Dictionary *(Pics)*中设置为当前表单上的PictureBox (代码运行的地方),名称为“PictureBox(x)”,其中x是您的增量整数某种价值。奇怪的是,你要求第一个实例的那个图片框(那就是结尾的(0)部分)

For Each frm As Form In Forms
    pics(frm) = Me.Controls("PictureBox" + CStr(i + 1))(0)
Next

从pics(frm)调用的方法基本上只获取或设置字典中现有项的值,因为字典尚未加载任何内容,Pics为空,在任何时候你都没有添加任何内容字典的形式,因此根本没有设置。

实现键值赋值的更合适的方法如下,但是仅仅设置表单的背景图像仍然是过度的

Sub BuildDictionary()
    '1. Declare the array of forms and the dictionary of (Key,Values) of type (Form,PictureBox)
    Dim Forms As New List(Of Form) 'list of forms that you want to assign BG
    Dim Pics As New Dictionary(Of Form, PictureBox) 'declare your dictionary list ("Key","Value") = (Form,Picturebox)
    With Forms 'fill the list
        .Add(Me)
        .Add(Form1)
        .Add(Form2)
        .Add(Form3)
    End With

    '2. Snag the picturebox we want to assign to the forms
    Dim PictureBoxToAssign As PictureBox = DirectCast(Me.Controls("PictureBox" + CStr(i + 1)), PictureBox) 'grab your picturebox

    '3 option 1 (prefered)
    '#### Either Do this next
    Pics.Clear() 'if your logic allows that you can clear the dictionary first
    For x As Integer = 0 To Forms.Count - 1 'for each form in the array
        Pics.Add(Forms(x), PictureBoxToAssign) 'add the form and picturebox to the dictionary            
    Next

    '3 option 2 (only if you cannot clear the dictionary)
    '#### Or Do this
    'you cannot clear the dictionary first due to logic
    For x As Integer = 0 To Forms.Count - 1 'for each form in the array
        'check existance of the pair
        If Pics.Contains(New Generic.KeyValuePair(Of Form, PictureBox)(Forms(x), PictureBoxToAssign)) Then
            Pics(Forms(x)) = PictureBoxToAssign 'update the value 
        Else
            Pics.Add(Forms(x), PictureBoxToAssign) 'add the new pair
        End If
    Next
End Sub

如果目标仅仅是将每个表单的背景图像设置为图片框的图像,那么可能更快更有效的路线可能是以下示例

Sub SetBG()
    Dim Forms As Form() = {Me, Form1, Form2, Form3} 'array of forms that you want to assign BG, occupies less memory than a list
    Dim PictureBoxToAssign As PictureBox = DirectCast(Me.Controls("PictureBox" + CStr(i + 1)), PictureBox) 'grab your picturebox
    For x As Integer = 0 To Forms.Count - 1 'for each form in the array
        Forms(x).BackgroundImage = PictureBoxToAssign.Image 'assign the image to the background      
    Next
End Sub

这里要记住的重要一点是,当以任何方式更改对象时,尽管可能在迭代数组内的对象集合时,不得使用“for each obj as”输入对象数组“方法,即不喜欢这个

For Each obj as ObjectType in ArrayofObjects
    Change the properties of obj = (BIG NO CAN DO)
Next

必须将循环与直接与集合中的对象进行交互,在本例中,使用for each中的每个索引

For x As Integer = 0 To Forms.Count - 1 'using an integer not the object itself
    'referencing the object through the index of the collection Forms(x)
    Forms(x).BackgroundImage = PictureBoxToAssign.Image 
Next

我希望这个答案能为黑暗带来光明

答案 2 :(得分:0)

分配给Pics字典的代码对我来说是错误的。要将新项添加到字典,您不能只分配给该索引。您必须使用.Add()方法。

当您尝试分配尚不存在的密钥时,应抛出异常。这可以解释一次你的循环。您第一次进入循环,抛出异常,因此您的代码永远不会到达第二次迭代。如果某个地方你吞下这个例外,你就永远不会知道。

Sub Butt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Butt.Click
    Dim Forms As New List(Of Form)
    Dim Pics As New Dictionary(Of Form, PictureBox)
    Forms.Add(me)
    Forms.Add(form2)
    Forms.Add(form3)
    Forms.Add(form4)

    For Each frm As Form In Forms
        pics.Add(frm, Me.Controls("PictureBox" + CStr(i + 1))(0))
    Next