0

Example-I have a person class

Public Class Person
Private _fname As String
Public Property Fname() As String
    Get
        Return _fname
    End Get
    Set(ByVal value As String)
        _fname = value
    End Set
End Property
Private _lname As String
Public Property Lname() As String
    Get
        Return _lname
    End Get
    Set(ByVal value As String)
        _lname = value
    End Set
End Property
Private _age As Integer
Public Property Age() As Integer
    Get
        Return _age
    End Get
    Set(ByVal value As Integer)
        _age = value
    End Set
End Property

End Class

  Dim people As New List(Of Person)
    people.Add(New Person With {.Fname = "Alice", .Lname = "Apples", .Age = 1})
    people.Add(New Person With {.Fname = "Bob", .Lname = "Banana", .Age = 2})
    people.Add(New Person With {.Fname = "Charlie", .Lname = "Cherry", .Age = 3})
    people.Add(New Person With {.Fname = "Dave", .Lname = "Durian", .Age = 4})
    people.Add(New Person With {.Fname = "Eric", .Lname = "EggPlant", .Age = 10})

    Dim filteredPerson = From person In people
    filteredPerson.Where(Function(fp) fp.Fname = "Bob")

    Dim finalList = filteredPerson.ToList
    For Each p In finalList
        Debug.Print("FNAME: " + p.Fname)
    Next

This still returns all 5 people, like the where is not being applied, what am I doing wrong?

I would also like to be able to pass a list of names and return only those

  Dim searchList As New List(Of String)
    searchList.Add("Bob")
    searchList.Add("Dave")

    Dim filteredPerson = From person In people
    For Each s In searchList
        Dim innerName As String = s
        filteredPerson.Where(Function(fp) fp.Fname = innerName)
    Next
    Dim finalList = filteredPerson.ToList
    For Each p In finalList
        Debug.Print("FNAME: " + p.Fname)
    Next
Cœur
  • 37,241
  • 25
  • 195
  • 267
Eric
  • 3,027
  • 6
  • 29
  • 34

2 Answers2

2

The problem is that Where doesn't change the collection. It returns the newly filtered collection.

Try this:

 Dim filteredPerson = people.Where(Function(fp) fp.Fname = "Bob")

(By the way, I don't see anything dynamic in here... where are you using dynamic LINQ?)

To add multiple Where clauses, you'll want something like this:

Dim searchList As New List(Of String)
searchList.Add("Bob")
searchList.Add("Dave")

Dim filteredPerson As IEnumerable(Of String) = people
For Each s In searchList
    Dim innerName As String = s
    filteredPerson = filteredPerson.Where(Function(fp) fp.Fname = innerName)
Next
Dim finalList = filteredPerson.ToList
For Each p In finalList
    Debug.Print("FNAME: " + p.Fname)
Next

However, I don't believe that's actually what you want to do. Each Where clause is going to insist that Fname is the specified name - and it's not going to be both Bob and Dave! I think you actually want something which can be expressed much more simply:

Dim searchList As New List(Of String)
searchList.Add("Bob")
searchList.Add("Dave")

Dim filteredPerson = people.Where(Function(fp) searchList.Contains(fp.Fname))
Dim finalList = filteredPerson.ToList
For Each p In finalList
    Debug.Print("FNAME: " + p.Fname)
Next

All we want to know is whether Fname is in searchList, which is what Contains does.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • It is in the last code section, where I want to be able to pass in a list of names adding where clauses for each name, in that example I would expect a list(of Person) with 2 items Bob & Dave – Eric Sep 10 '09 at 16:51
  • That's it! That's exactly what I was trying to convey. Thanks – Eric Sep 10 '09 at 16:55
  • @Jon: I don't know the syntax. Could you give an example for 2nd case with a JOIN instead? – shahkalpesh Sep 10 '09 at 16:55
  • @shahkalpesh: I have no idea what you mean, I'm afraid. Which second case, and why would you want a join? – Jon Skeet Sep 10 '09 at 16:58
  • +1 for Contains. People really struggle with that. I believe that it's because you are doing the operation on the second data set and using the first element as the parameter, whereas the procedural approach is to think 'for each element in my search list'... – Kirk Broadhurst Nov 23 '09 at 11:36
0
Dim people As New List(Of Person)
people.Add(New Person With {.Fname = "Alice", .Lname = "Apples", .Age = 1})
people.Add(New Person With {.Fname = "Bob", .Lname = "Banana", .Age = 2})
people.Add(New Person With {.Fname = "Charlie", .Lname = "Cherry", .Age = 3})
people.Add(New Person With {.Fname = "Dave", .Lname = "Durian", .Age = 4})
people.Add(New Person With {.Fname = "Eric", .Lname = "EggPlant", .Age = 10}) 

Dim searchList As New List(Of String)
searchList.Add("Bob")
searchList.Add("Dave")

dim filteredItems = from p in people _
join i in searchList on p.FName equals i _
select p

dim personFound as Person

for each personFound in filteredItems
    Console.WriteLine(personFound.Lname)
next
shahkalpesh
  • 33,172
  • 3
  • 63
  • 88