Generic List Find.

  • Thread starter Thread starter Satish Itty
  • Start date Start date
S

Satish Itty

How do I write the following c# code in vb

Product FindProduct(string code)
{
List<Product> products = getProducts();
return products.Find(delegate(Product bo)
{ return bo.Code == code; });
}
 
How do I write the following c# code in vb

Product FindProduct(string code)
{
List<Product> products = getProducts();
return products.Find(delegate(Product bo)
{ return bo.Code == code; });



}- Hide quoted text -

- Show quoted text -

Function FindProduct (ByVal code As String) As Product
Dim products As List(Of Product) = GetProducts()
Dim pred As New PredicateClass(code)

Return products.Find (AddressOf pred.PredicateFunction)
End Function

Private Class PredicateClass
Private code As String
Public Sub New (ByVal code As String)
Me.code = code
End Sub

Public Function PredicateFunction (ByVal bo As Product) As Boolean
Return bo.Code = Me.code
End Function
End Class

Anyway, that should be a good approximation (I just did that off the
top of my head, so it's not tested, and may actually contain some
stray C# syntax :)... Man am I grateful for anonymous methods in C# :)
 
Why not just code it the straight forward way?

Function FindProduct(code as string) as Product
dim products as List(of Product) = GetProduct()
for each p as product in Products
if p.code = code then
return p
end if
return nothing
end function
 
Terry said:
Why not just code it the straight forward way?

Function FindProduct(code as string) as Product
dim products as List(of Product) = GetProduct()
for each p as product in Products
if p.code = code then
return p
end if
return nothing
end function

Can you change or overload the GetProduct to take a code as a parameter.
Seems like alot of extra processing to retrieve all the info and then filter
it.

LS
 
I had assumed in this example that GetProducts() was just going to return a
reference to an existing List. The real point I was making here, was that,
while both Satish and Tom were lamenting the lack of 'anonymous methods ' in
VB, why would you use one in this case. And I think that holds true for both
C# and VB. That is unless 'Find' has some built in speed improvemnt that
will make up for a totally un-needed function call.
 
Well, I stand corrected.... Find is faster then using Enumeration, even when
you have to go through the contortions that Tom suggested. The results for
the test code that follows were:

Starting test.....
Elasped time for Enumeration is 00:00:13.0926257
Elasped time for Find is 00:00:12.4814362

and the test I used....

Module Module1
Dim Products As New List(Of Product)
Dim TestCount As Integer = 10000

Sub Main()
Dim I As Integer
For I = 1 To TestCount
Dim p As New Product(I)
Products.Add(p)
Next
Dim sw As New System.Diagnostics.Stopwatch
Console.WriteLine("Starting test.....")
sw.Start()
For I = 1 To TestCount
FindProduct(I.ToString)
Next
sw.Stop()
Console.WriteLine("Elasped time for Enumeration is {0}", sw.Elapsed)
sw.Reset()
sw.Start()
For I = 1 To TestCount
FindProduct2(I.ToString)
Next
sw.Stop()
Console.WriteLine("Elasped time for Find is {0}", sw.Elapsed)
Console.ReadLine()
End Sub

Private Function FindProduct(ByVal code As String) As Product
For Each p As Product In Products
If p.Code = code Then Return p
Next
Return Nothing
End Function

Function FindProduct2(ByVal code As String) As Product
Dim pred As New PredicateClass(code)

Return products.Find(AddressOf pred.PredicateFunction)
End Function

Public Class Product
Private _Code As String
Public ReadOnly Property Code() As String
Get
Return _Code
End Get
End Property

Public Sub New(ByVal c As Integer)
_Code = c.ToString
End Sub
End Class

Private Class PredicateClass
Private code As String
Public Sub New(ByVal code As String)
Me.code = code
End Sub

Public Function PredicateFunction(ByVal bo As Product) As Boolean
Return bo.Code = Me.code
End Function
End Class

End Module
 
Thanks terry for comparing both options.
Lloyd The reason for my approach was because the products list is cached
and all getProducts() does it to get a list from the cache. So whether I
overload getProducts() to take the parameter or not I will have to do
this process somewhere.
So I guess I will go with toms suggestion of predicateclass
 
Thanks terry for comparing both options.
Lloyd The reason for my approach was because the products list is cached
and all getProducts() does it to get a list from the cache. So whether I
overload getProducts() to take the parameter or not I will have to do
this process somewhere.
So I guess I will go with toms suggestion of predicateclass
 
Well, I stand corrected.... Find is faster then using Enumeration, even when
you have to go through the contortions that Tom suggested. The results for
the test code that follows were:

Starting test.....
Elasped time for Enumeration is 00:00:13.0926257
Elasped time for Find is 00:00:12.4814362

and the test I used....

Module Module1
Dim Products As New List(Of Product)
Dim TestCount As Integer = 10000

Sub Main()
Dim I As Integer
For I = 1 To TestCount
Dim p As New Product(I)
Products.Add(p)
Next
Dim sw As New System.Diagnostics.Stopwatch
Console.WriteLine("Starting test.....")
sw.Start()
For I = 1 To TestCount
FindProduct(I.ToString)
Next
sw.Stop()
Console.WriteLine("Elasped time for Enumeration is {0}", sw.Elapsed)
sw.Reset()
sw.Start()
For I = 1 To TestCount
FindProduct2(I.ToString)
Next
sw.Stop()
Console.WriteLine("Elasped time for Find is {0}", sw.Elapsed)
Console.ReadLine()
End Sub

Private Function FindProduct(ByVal code As String) As Product
For Each p As Product In Products
If p.Code = code Then Return p
Next
Return Nothing
End Function

Function FindProduct2(ByVal code As String) As Product
Dim pred As New PredicateClass(code)

Return products.Find(AddressOf pred.PredicateFunction)
End Function

Public Class Product
Private _Code As String
Public ReadOnly Property Code() As String
Get
Return _Code
End Get
End Property

Public Sub New(ByVal c As Integer)
_Code = c.ToString
End Sub
End Class

Private Class PredicateClass
Private code As String
Public Sub New(ByVal code As String)
Me.code = code
End Sub

Public Function PredicateFunction(ByVal bo As Product) As Boolean
Return bo.Code = Me.code
End Function
End Class

End Module
--
Terry






- Show quoted text -

Terry, thanks for the compare! I have never thought of it in terms of
performance, but asthetics :) But based on your test (which sparked a
little debate here :), we had a look at the implementation of
Find.... It turns out the difference is that find using for instead
of foreach to iterate the loop. For is faster then for each...
 
A little side note here. It turns out that whichever test runs second has an
advantage! By reversing the order, the results were reversed! Not sure I
understand why. Also I thought to be fair I would add a test using a
For...Next loop to the mix and here are the results:

Starting test.....
Elasped time for Find is 00:00:12.9557964
Elasped time for Enumeration is 00:00:12.6141232
Elasped time for For...Next is 00:00:12.2901846

and the third FindProduct function is:
Private Function FindProduct3(ByVal code As String) As Product
Dim J As Integer
Dim p As Product
For J = 0 To Products.Count - 1
p = Products(J)
If p.Code = code Then Return p
Next
Return Nothing
End Function
 
A little side note here. It turns out that whichever test runs second has an
advantage! By reversing the order, the results were reversed! Not sure I
understand why. Also I thought to be fair I would add a test using a
For...Next loop to the mix and here are the results:

Starting test.....
Elasped time for Find is 00:00:12.9557964
Elasped time for Enumeration is 00:00:12.6141232
Elasped time for For...Next is 00:00:12.2901846

and the third FindProduct function is:
Private Function FindProduct3(ByVal code As String) As Product
Dim J As Integer
Dim p As Product
For J = 0 To Products.Count - 1
p = Products(J)
If p.Code = code Then Return p
Next
Return Nothing
End Function
--
Terry





- Show quoted text -

We did our tests in C#, and reversed the orders... Consistently, the
methods from slowest to fastest were:

For Each (foreach)
Find
For (for)

I'm not sure what would be the difference in VB.NET
 
Yes, interesting is right! I changed the testing around to do 3 of one type,
then changed to 3 of the next type etc and ran each a couple of times. The
results were:

For...Next average time of 35.2
Find average time of 35.5
For Each average time of 36.2

not a lot of difference for 30,000 lookups and nothing you could ever notice
in a normal windows form UI type application. Might make a difference in
some large scale 'batch' process, but again nothing huge. Funny that the
results are reversed for C#....
 
Yes, interesting is right! I changed the testing around to do 3 of one type,
then changed to 3 of the next type etc and ran each a couple of times. The
results were:

For...Next average time of 35.2
Find average time of 35.5
For Each average time of 36.2

not a lot of difference for 30,000 lookups and nothing you could ever notice
in a normal windows form UI type application. Might make a difference in
some large scale 'batch' process, but again nothing huge. Funny that the
results are reversed for C#....

Actually, those results are consistent with ours, we also ran the test
on multple types - object, integer, string and in different orders. I
listed my results from slowest to fastest, yours are fastest to
slowest :)

Like I said, Find is implemented using For...Next (for). So, the
slight speed difference between for and find, has to do with the
overhead of invoking the predicate delegate....
 
Back
Top