tags:

views:

2147

answers:

6

Hi, I have something that is driving me absolutely crazy...

    Public Function GetAccountGroups() As IList(Of AccountGroup)
        Dim raw_account_groups As IList(Of AccountGroup)
        raw_account_groups = _repository.GetAccountGroups().ToList()
        Dim parents = (From ag In raw_account_groups _
                      Where ag.parent_id = 0 _
                      Select ag).ToList()

        parents(0).sub_account_groups = (From sag In raw_account_groups _
                               Where sag.parent_id = 0 _
                                Select sag).ToList()

        Dim sql_func As Func(Of AccountGroup, List(Of AccountGroup)) = Function(p) _
                                                                      (From sag In raw_account_groups _
                                                                       Where sag.parent_id = p.id _
                                                                       Select sag).ToList()

        parents.ForEach(Function(p) p.sub_account_groups = sql_func(p))

        Return parents
    End Function

The line "parents.ForEach(Function(p) p.sub_account_groups = sql_func(p))" has this error...

Operator '=' is not defined for types 'System.Collections.Generic.IList(Of st.data.AccountGroup)' and 'System.Collections.Generic.List(Of st.data.AccountGroup)'.

but I really can't see how it is any different from this code from Rob Connery

public IList<Category> GetCategories() {
IList<Category> rawCategories = _repository.GetCategories().ToList(); var parents = (from c in rawCategories 
where c.ParentID == 0
select c).ToList();
 parents.ForEach(p =>
{
p.SubCategories = (from subs in rawCategories
where subs.ParentID == p.ID
select subs).ToList();
});

return parents; 
}

which compiles perfectly... what am I doing incorrectly?

Thanks in advance, David

A: 

I haven't used VB.NET since moving to C# 3.0, but it seems like it could be a type inference issue. The error is a bit odd since List implements IList, so the assignment should work. You can say "p.ID = 123" for the lambda and things seem to work.

For anyone else interested in looking into it, here is code that you can paste into a new VB.NET console project to demonstrate this issue:

Module Module1
    Sub Main()
    End Sub
End Module

Class AccountGroup
    Public parent_id As Integer
    Public id As Integer
    Public sub_account_groups As List(Of AccountGroup)
End Class
Class AccountRepository
    Private _repository As AccountRepository

    Public Function GetAccountGroups() As IList(Of AccountGroup)
        Dim raw_account_groups As IList(Of AccountGroup)
        raw_account_groups = _repository.GetAccountGroups().ToList()
        Dim parents = (From ag In raw_account_groups _
                       Where ag.parent_id = 0 _
                       Select ag).ToList()
        parents(0).sub_account_groups = (From sag In raw_account_groups _
                                         Where sag.parent_id = 0 _
                                         Select sag).ToList()

        Dim sql_func As Func(Of AccountGroup, List(Of AccountGroup)) = Function(p) _
                                                                            (From sag In raw_account_groups _
                                                                             Where sag.parent_id = p.id _
                                                                             Select sag).ToList()



        parents.ForEach(Function(p) p.sub_account_groups = sql_func(p))
        Return parents
    End Function
 End Class
Jeff Moser
A: 

Instead of p.sub_account_groups = sql_func(p), try

p.sub_account_groups Is sql_func(p)

if you're trying to see whether they're the same object, or

p.sub_account_groups.Equals(sql_func(p))

if you're trying to see if they're equal in some other fashion. (Most likely you're looking for Is, though.)

Kyralessa
beautiful! cheers
Sorry but this comment is nonsense. The OP doesn't try to compare anything here (at least that wouldn't make sense). Your comment about `Equals`, while technically correct, is also misleading because the operator `=` usually behaves the same way as `Equals` and neither is properly defined for lists.
Konrad Rudolph
He's doing an assignment, not comparison.
Richard Hein
I agree with Richard. The original code from Rob is doing an assignment. It has to be broken out into a For Each loop.
BlackMael
A: 

I guess "ag.parent_id = 0" should be Where ag.parent_id == 0?

Andy
Not in VB ... = is correct.
Richard Hein
+6  A: 

Lambda's in VB.Net have to return a value, so your equal sign ('=') is being intepreted as a comparison (so that the lambda returns a boolean), rather than an assignment.

chyne
chyne is correct. Your code would work fine in C#. I made a similar example to test it. Also you cannot have multiple lines, so you can't even add a Return. So you have to use a ForEach loop.
Richard Hein
+3  A: 

The accepted answer here is probably wrong, based on your code. chyne has given the correct clue: lambdas in VB always have return values (unlike in C#), statement lambdas are introduced in the next version though.

In the meantime, you simply can't use this code in VB. Use a regular loop instead:

For Each p In parents
    p.sub_account_groups = sql_func(p)
Next

The next version of VB (available as a Beta since yesterday) would allow the following code to be written:

parents.ForEach(Sub (p) p.sub_account_groups = sql_func(p))
Konrad Rudolph
You need the EndSub don't you? Or did they remove it in Beta1?
Richard Hein
@Auxon: you don't need it for one-liners as above. At least, you didn't used to. I haven't tested the beta yet: I'm using OS X.
Konrad Rudolph
A: 

Use Sub for assignment operator: parents.ForEach(Sub(p) p.sub_account_groups = sql_func(p))

BSalita