0

As described here, in C#, using classes like the following:

public class Node {
    public NodeData Data { get; set; } = new NodeData();
    public List<Node> Children { get; set; } = new List<Node>() { null };
}

public class NodeData {
    public string Name { get; set; }
}

it is possible to generate expression trees (using the compiler) which have an instance of MemberMemberBinding:

Expression<Func<Node>> expr = () => new Node() {
    Data = {
        Name = "hello world"
    }
};

or MemberListBinding:

Expression<Func<Node>> expr1 = () => new Node() {
    Children = {
        new Node(), new Node()
    }
};

When trying to do the same thing in VB.NET, the code doesn't compile; neither the MemberMemberBinding code nor the ListBinding code:

Class Node
    Property Data As NodeData = New NodeData
    Property Children As List(Of Node) = New List(Of Node)
End Class
Class NodeData
    Property Name As String
End Class

' Compiler error -- Expression cannot be converted to expression tree
' When assigning to Func(Of Node) instead of Expression -- Name is not a member of Node
Dim expr As Expression(Of Func(Of Node)) = Function() New Node With {
    .Data = {
        .Name = "abcd"
    }
}

' Compiler error -- value of type Node() cannot be converted to List(Of Node)
Dim expr1 As Expression(Of Func(Of Node)) = Function() New Node With {
    .Children = {
        New Node, New Node
    }
}

Is there any way to have the VB.NET compiler generate MemberMemberBinding and MemberListBinding instances?

Zev Spitz
  • 13,950
  • 6
  • 64
  • 136
  • `Can similar expression trees be generated via the VB.NET compiler?`, have you tried it, what happens? – Trevor Apr 01 '19 at 19:22
  • What error do you get? I've been able to use `Expression(Of Func(Of ...))` in VB. The only problem I encountered was that there are certain situations where VB will wrap the lambda in a unary conversion to `Object`; as long as the receiver is aware of this, it's easy to unpack the expression and pull out the expression inside the conversion (in my case, it was a `MemberExpression`). – Craig Apr 02 '19 at 13:06
  • @Craig Updated. _I've been able to use `Expression(Of Func(Of ...))`_ So have I. The problem is in initializing properties and collection members using a nested initializer. – Zev Spitz Apr 02 '19 at 18:05
  • In the first one, you need `.Data = New NodeData With {.Name = "abcd"}` for a simple assignment to work. – Craig Apr 02 '19 at 18:28
  • For the second, similarly it's `.Data = New NodeData With {.Children = New List(Of Node) From {...}}` – Craig Apr 02 '19 at 18:29
  • @Craig What you've written works, but these evaluate in the expression tree to `MemberAssignment`, not `MemberMemberBinding` or `ListBinding`. The corresponding first C# syntax is `MemberMemberBinding` -- it doesn't create a new instance of `NodeData` at `.Data`, but rather modifies the existing instance already there, and if there is no such instance it will cause a `NullReferenceException`. Same goes for `.Children` -- the C# syntax doesn't create a new `List(Of Node)`, but rather adds the new instances to the existing `List(Of Node)` at `.Children`. – Zev Spitz Apr 02 '19 at 19:41
  • I'm not sure that this kind of expression is supported in VB. It doesn't seem like it; I couldn't find a way to express it for a simple assignment. – Craig Apr 02 '19 at 20:40

0 Answers0