【问题标题】:Error code using Linq to add to a variable使用 Linq 添加到变量的错误代码
【发布时间】:2013-03-27 02:32:48
【问题描述】:

我将从问题开始,然后描述该过程的工作原理。

我收到一条错误消息:

“System.Collections.Generic.IEnumerable(Of LunchMoneyGame.LunchMoneyMainForm.Group)”类型的值无法转换为“LunchMoneyGame.LunchMoneyMainForm.Group”。

指出问题的蓝色下划线位于运算符右侧的Dim obj As LunchMoneyGame.LunchMoneyMainForm.Group = From r In temp Where r.ID = Number Select r

我知道这与明确性有关

--

这是我正在转换为文字游戏的桌面纸牌游戏。

此子程序的目标是从玩家手中减去一张牌并将其添加到弃牌堆中。一旦添加到弃牌堆中,我就会调用弃牌堆,将牌从弃牌堆移到牌堆。

问题从数字生成器开始。 我正在做的是从牌组中随机挑选一张牌。通过生成卡片组中卡片的卡片 ID。使用 linq 生成 ID 后,生成的数字会拿一张卡片,然后将卡片添加到玩家库存(数量整数),然后从牌组中减去。

T 代表轮到谁了。目前出于测试目的,我仅根据 T 变量为 2 名玩家编写了代码。

  Private Sub GrabFromDeckAndDiscard()
        Dim CardCheckBoxInteger As Integer
        'ReDeclare CheckBox Array for Private sub
        Dim CardCheckBoxArray() As CheckBox = {CardCheckBox1, CardCheckBox2, CardCheckBox3, CardCheckBox4, CardCheckBox5}
        'Discard
        Select Case T
            Case 0
                Player1HandGroup(NumberArray(Checks)).QuantityInteger -= 1
            Case 1
                Player1HandGroup(NumberArray(Checks)).QuantityInteger2 -= 1
            Case 2
                Player1HandGroup(NumberArray(Checks)).QuantityInteger3 -= 1
            Case 3
                Player1HandGroup(NumberArray(Checks)).QuantityInteger4 -= 1
            Case 4
                Player1HandGroup(NumberArray(Checks)).QuantityInteger5 -= 1
        End Select
        'Add Card to Discard Pile
        DiscardGroup(NumberArray(Checks)).QuantityInteger += 1
        'Shuffle Deck from Discard Pile if Deck is out of cards
        Call DiscardPile()
        'Reset Number Generator, unless weapon isn't discard
        Dim temp As IEnumerable(Of LunchMoneyGame.LunchMoneyMainForm.Group) = From r In DeckGroup Where r.QuantityInteger > 0 Select r

        If temp IsNot Nothing AndAlso temp.count > 0 Then
            Number = (temp(Rnd.Next(0, temp.Count)).ID)
            ' ** Edit **: This will give you the actual object to be manipulated
            Dim obj As LunchMoneyGame.LunchMoneyMainForm.Group = (From r In temp Where r.ID = Number Select r).Single


            Dim PlayerQuantitySubtractionInteger As Integer
            For PlayerQuantitySubtractionInteger = ChecksDynamicA To ChecksDynamicB
                ' ** Edit **
                obj.QuantityInteger -= 1
                'Select the Player depending value of T
                Select Case T
                    Case 0
                        Player1HandGroup(Number).QuantityInteger += 1
                    Case 1
                        Player1HandGroup(Number).QuantityInteger2 += 1
                    Case 2
                        Player1HandGroup(Number).QuantityInteger3 += 1
                    Case 3
                        Player1HandGroup(Number).QuantityInteger4 += 1
                    Case 4
                        Player1HandGroup(Number).QuantityInteger5 += 1
                End Select
                CardTypeArray(PlayerQuantitySubtractionInteger) = Player1HandGroup(Number).CardType
                CardCheckBoxArray(TextBoxInteger).Text = Player1HandGroup(Number).CardNameString
                NumberArray(PlayerQuantitySubtractionInteger) = Number
            Next PlayerQuantitySubtractionInteger
        End If

        'Switch to next player
        Select Case T
            Case 0
                For CardCheckBoxInteger = 0 To 4
                    CardCheckBoxArray(CardCheckBoxInteger).Text = Player1HandGroup(NumberArray(CardCheckBoxInteger + 5)).CardNameString
                Next
                T += 1
            Case 1
                If GameSize = 2 Then
                    For CardCheckBoxInteger = 0 To 4
                        CardCheckBoxArray(CardCheckBoxInteger).Text = Player1HandGroup(NumberArray(CardCheckBoxInteger)).CardNameString
                    Next CardCheckBoxInteger
                    T -= 1
                End If
                If GameSize > 2 Then
                    T += 1
                End If
            Case 2
            Case 3
            Case 4

        End Select
        Label1.Text = T.ToString

        'Clear Check Boxes when turn is finished
        For CardCheckBoxInteger = 0 To 4
            CardCheckBoxArray(CardCheckBoxInteger).Checked = False
        Next

        'Turn off play button
        PlayButton.Enabled = False
    End Sub

【问题讨论】:

    标签: vb.net linq


    【解决方案1】:
    From r In temp 
    Where r.ID = Number 
    Select r
    

    返回与 Where 子句匹配的所有内容的集合(有关 MSDN 文档,请参阅 this)。 .NET 将其表示为 IEnumerable,这意味着可以迭代的事物的集合(例如,使用 For 循环或类似的东西)。

    即使您的条件是 =,也不会自动返回一条记录(也可能存在不返回任何元素的条件,例如没有任何元素与相等条件匹配或在多个事物符合相等条件)。

    为了表明您只需要一个元素,您可以使用FirstSingleFirstOrDefaultSingleOrDefault 方法。

    例如:

     Dim obj As LunchMoneyGame.LunchMoneyMainForm.Group = (From r In temp Where r.ID = Number Select r).Single()
    

    这将为您提供LunchMoneyGame.LunchMoneyMainForm.Group 类型的对象,我认为您在这种情况下正在寻找它。

    顺便说一句,了解我上面概述的方法之间的区别也不错。以我的外行观点(因为我不是专家):

    • First 返回集合中的第一项,如果集合为空则抛出异常
    • FirstOrDefault 返回集合中的第一项,如果为空则返回 null
    • Single 返回集合中的唯一一项,如果集合中没有一项,则抛出异常
    • SingleOrDefault 返回集合中的第一项,如果集合为空,则返回 null,如果集合超过 1 个元素,则抛出异常

    所以在您的情况下,由于您应该只匹配具有= 条件的单个项目,我建议使用SingleSingleOrDefault

    PS.抱歉,当我在上面说 null 时,在 VB.NET 中将是 Nothing

    【讨论】:

    • 现在当我打出一张牌时,它会增加一张随机牌的+5。所以现在在我的玩家阵列中,他理论上有 9 张牌。当玩家打出他们的牌时,它会移除打出的牌(就像假设的那样),保留手中剩余的 4 张,然后添加 5 张新牌。我代表卡片的 5 个复选框都填充了这 5 张卡片。目标是从库存中取出 1 张牌并打入弃牌堆,从牌库中取出 1 张随机牌并加入玩家手牌。所以总的来说,代码可以做所有事情,除了取正确数量的随机卡。
    • 如果您需要更多帮助,我认为您需要发布完整的源代码,因为我不确定您的代码中的某些内容来自何处。但是,我怀疑问题出在您的 For 循环 For PlayerQuantitySubtractionInteger = ChecksDynamicA To ChecksDynamicB 以及您如何在其中添加和删除数量
    • 我应该编辑问题,还是以某种方式向您发送源代码?
    • 请编辑问题。如果您有可下载的源代码,如果您提供链接,我可以看看,但我不知道围绕这些事情的 SO 礼仪,因为我还是该网站的新手
    • 好的,将更改添加到编辑中。我试过 obj.QuantityInteger -= 1 位于循环内和循环外 (For PlayerQuantitySubtractionInteger = ChecksDynamicA To ChecksDynamicB)。
    猜你喜欢
    • 2012-07-11
    • 2020-01-07
    • 2010-09-30
    • 1970-01-01
    • 1970-01-01
    • 2018-07-05
    • 2018-02-17
    • 2021-09-04
    • 2020-02-03
    相关资源
    最近更新 更多