【问题标题】:How to change a value in list of class?如何更改类列表中的值?
【发布时间】:2017-05-02 06:44:14
【问题描述】:

给定这样的课程

Public Class ItemPanel

    Inherits Panel

    Public Name as string
    Public Quantity As Integer

End Class

还有这样的列表

Public li_ip As New List(Of ItemPanel)

我有一个子会帮我在单击按钮时将ItemPanel添加到li_ip列表中,每个单击的按钮也会将其文本添加到li_item中,因此当一个按钮单击两次时,只有第一次会将ItemPanel添加到li_ip,第二次单击只会改变 ItemPanel 中的数量

Private Sub RefreshOrdered(sender As Object)
        If Not li_item.Contains(sender.Text) Then

            Dim pn As ItemPanel
            With pn
                .Name = sender.Text
                .Quantity = 1
            End With

            li_ip.Add(pn)

        Else

            'Here I want to change the quantity in ItemPanel depend on the sender.Text

        End If
End Sub

那么我怎样才能得到我想要的结果呢?后面应该写什么?

【问题讨论】:

  • 要从列表中获取项目,此答案将有所帮助:stackoverflow.com/a/200165/5152045
  • 在我看来你想要一个Dictionary(Of String, Integer)。你检查过List以外的容器吗?

标签: vb.net list class


【解决方案1】:

要通过其属性之一搜索list item,可以使用List(Of T).Find Method 。在这种情况下,List 由变量 li_ip 引用,用于查找 list item 的属性是 Name

根据 MSDN 文档,Find 方法返回 第一个 元素,该元素与指定谓词定义的条件匹配(如果找到);否则,类型 T 的默认值

T 的默认值ItemPanelNothing 因为ItemPanel 是一个引用类型。因此,当Find 实际找到item 时,它的Quantity 可以递增。高温

Dim itm As ItemPanel = li_ip.Find(function(c) c.Name = sender.Text)
If Not itm Is Nothing Then
    itm.Quantity = itm.Quantity + 1   
End If 

完整的代码可能如下所示。

Private Sub RefreshOrdered(sender As Object)
    ' Notice that Contains like this won't work:
    If Not li_ip.Contains(sender.Text) Then

        Dim pn As ItemPanel
        ' shouldn't here the New keyword be used?
        ' pn = New ItemPanel()  
        With pn
            .Name = sender.Text
            .Quantity = 1
        End With

        li_ip.Add(pn)

    Else

        'Here I want to change the quantity in ItemPanel depend on the sender.Text
        Dim itm As ItemPanel = li_ip.Find(function(c) c.Name = sender.Text)
        If Not itm Is Nothing Then
            itm.Quantity = itm.Quantity + 1   
        End If 

    End If
End Sub 

注意: LINQ 也可以使用,但Find 可能更快。参见例如this answer.


编辑:

这里是重构版本,其中 Find 方法只被调用一次,就像 @Default 提到的那样。

Private Sub RefreshOrdered(sender As Object)
    Dim panelName As string = sender.Text
    Dim panel As ItemPanel = li_ip.Find(function(p) p.Name = panelName) 
    If Not panel Is Nothing Then
        ' Panel with given name exists already in list, increment Quantity
        panel.Quantity += 1   
    Else 
        ' Panel with such name doesn't exist in list yet, add new one with this name
        Dim newPanel As ItemPanel
        newPanel = New ItemPanel()  
        With newPanel
            .Name = panelName
            .Quantity = 1
        End With
        li_ip.Add(newPanel)
    End If 
End Sub

也可以使用LINQ 代替Find,例如像这样:

Dim panel As ItemPanel = li_ip.SingleOrDefault(function(p) p.Name = panelName)

【讨论】:

  • 您能否添加一些文字来解释为什么您使用该代码?
  • 也许你应该先调用Find,然后检查返回值是否为null。现在您正在遍历列表两次(一次使用.Contains,然后使用.Find),这似乎没有必要。
  • @Default 是的,你是绝对正确的!我只是想以它的构建方式回答这个问题。但是是的,代码可以这样重构。
猜你喜欢
  • 2020-01-28
  • 1970-01-01
  • 2019-06-27
  • 2020-01-29
  • 1970-01-01
  • 2017-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多