Find an item in an List(Of T) by values x, y, and z
Solution 1
Here's two ways that I came up with to accomplish your question. One way uses a LINQ query syntax to filter; the second uses a custom object to hold your predicate parameters and then uses that object to perform the filter.
Using the LINQ syntax in your Item property:
Default Public Overridable Shadows ReadOnly Property Item(ByVal x As String, ByVal y As Integer, ByVal z As String) As IEnumerable(Of A)
Get
Return (From theA In Me
Where (theA.x = x And theA.y = y And theA.z = z)
Select theA)
End Get
End Property
The other way would be to create a PredicateParameter class to hold your parameters and also a delegated method that is used to execute the filter. I saw this on an MSDN comment - here's the link. Here's the class:
Class PredicateParams
Public Sub New(ByVal theA As A)
Criteria = theA
End Sub
Public Property Criteria As A
Public Function IsMatch(ByVal theA As A) As Boolean
Return (theA.x = Criteria.x And theA.y = Criteria.y And theA.z = Criteria.z)
End Function
End Class
And here's the property that is in the CollOfA class that uses it:
Public Overridable Shadows ReadOnly Property ItemPred(ByVal x As String, ByVal y As Integer, ByVal z As String) As IEnumerable(Of A)
Get
Dim predA As New A
predA.x = x
predA.y = y
predA.z = z
Dim pred As New PredicateParams(predA)
Return Me.FindAll(AddressOf pred.IsMatch)
End Get
End Property
Lastly, here's a console runner to test this.
Sub Main()
Dim mycoll As New CollOfA()
For index = 1 To 100
Dim anA As New A()
anA.x = (index Mod 2).ToString()
anA.y = index Mod 4
anA.z = (index Mod 3).ToString()
mycoll.Add(anA)
Next
Dim matched As IEnumerable(Of A) = mycoll.Item("1", 3, "2")
Dim matched2 As IEnumerable(Of A) = mycoll.ItemPred("1", 3, "2")
Console.WriteLine(matched.Count.ToString()) 'output from first search
Console.WriteLine(matched2.Count.ToString()) 'output from second search (s/b same)
Console.ReadLine()
End Sub
Hopefully this helps. There may be a more elegant way to do this, but I didn't see one. (BTW, I generally work with C#, so my VB.NET is a little rusty.)
Solution 2
If your class A is simple enough, you may be able to get away with a one-line default property getter and the Find method of your List, something like this:
Public Class CollOfA
Inherits List(Of A)
Default Public Overloads ReadOnly Property Item(ByVal x As String, ByVal y As Integer, ByVal z As String) As A
Get
Return Find(Function(a As A) (((a.x = x) AndAlso (a.y = y)) AndAlso (a.z = z)))
End Get
End Property
End Class
I did this in Visual Studio 2008, so I don't know how it'll work in other versions.
Related videos on Youtube
Comments
-
1977 almost 2 years
I have the following setup:
Class A property x as string property y as int property z as String End Class Class CollOfA inherits List(Of A) End Class
What I would like is an Item property in the collection that I can say:
dim c as new CollOfA c.item("this", 2, "that")
I have tried implementing the following in CollOfA:
Class CollOfA inherits List(Of A) Default Public Overridable Shadows ReadOnly Property Item(ByVal x As String, ByVal y As Integer, byval z as string) Get ' I want to do something like: ' ForEach item in me see if anything matches these three things End Get End Property End Class
I know about predicates, but I am struggling with how to set the criteria of the predicate (i.e. passing x, y, and z).
Has anyone implemented something similar?