0

I am using Dapper to query a flat list of items from a database, into a POCO class as follows:

Public Class Node
    Public Property Name As String
    Public Property ParentNodeName As String
    Public Property Children As IEnumerable(Of Node)
End Class

I am trying to use the accepted answer to this question, in order to create a tree out of the flat list.

The only caveat is that I am using VB.NET.

I have tried it a straightforward port of the C# solution:

nodes.ForEach(Function(n) n.Children = nodes.Where(Function(ch) ch.ParentNodeName = n.Name).ToList)

but it does not compile with the error

Error   BC30452 Operator '=' is not defined for types 'List(Of Node)' and 'List(Of Node)'.

The = symbol is interpreted as an equality operator, while I meant to use the assignment operator.

I have pasted the C# code into the telerik converter, and the converted code is:

Private Shared Function BuildTree(ByVal items As List(Of Category)) As IEnumerable(Of Category)
    items.ForEach(Function(i) CSharpImpl.__Assign(i.Categories, items.Where(Function(ch) ch.ParentId = i.Id).ToList()))
    Return items.Where(Function(i) i.ParentId Is Nothing).ToList()
End Function

Private Class CSharpImpl
    <Obsolete("Please refactor calling code to use normal Visual Basic assignment")>
    Shared Function __Assign(Of T)(ByRef target As T, value As T) As T
        target = value
        Return value
    End Function
End Class

It uses an helper class to solve this issue, but suggests a refactor to avoid this.

Hence the questions:

  • Is there a general way to disambiguate equality = and assignment = in VB.NET, without resorting to an helper class and a specific function to assignement

  • In this specific case, is there a simple refactor I can use to get rid of the issue?

Maxime
  • 1,245
  • 2
  • 14
  • 24

1 Answers1

2

That's because of VB.Net distinction between functions and subroutines.

Instead of

nodes.ForEach(Function(n) n.Children = nodes.Where(Function(ch) ch.ParentNodeName = n.Name).ToList)

use

nodes.ForEach(Sub(n) n.Children = nodes.Where(Function(ch) ch.ParentNodeName = n.Name).ToList)

When you use Function, the lambda expression is expected to return a value; and in your case it looks like it wants to return a boolean.

But you want to use a lambda expression that does not return anything (in your case, you want an assignment), you have to use Sub.

sloth
  • 99,095
  • 21
  • 171
  • 219
  • This is partly because in VB, assignment is a statement, not an expression (as distinct from C-heritage languages). So if you use `=` in an expression context, it will necessarily be interpreted as the equality comparison operator, since it can't be an assignment. – Craig Sep 26 '18 at 13:48