Following up on the last Roslyn preview way back in 2012, this week saw the availability of a new preview with a more complete compiler along with a few new language features for C# and VB. A lot of inspiration for these features seems to have come from the F# language.
The C# interactive shell from 2012 appears to be missing, perhaps ScriptCS is expected to fill this space, or you could just use F# interactive which already exists in Visual Studio.
On the language features side, C# 6 gets primary constructors for classes, heavily inspired by F#, and using static which brings parity with Java and VB.Net.
For me VB.Net gets the most interesting new feature in the form of Select Case TypeOf. which provides the first steps towards pattern matching.
Shapes
Taking a hierarchy of shapes as an example:
Public MustInherit Class Shape
End Class
Public Class Rectangle
Inherits Shape
Public Property Width As Integer
Public Property Height As Integer
End Class
Public Class Circle
Inherits Shape
Public Property Radius As Integer
End Class
Sub Main()
Dim shape As Shape = New Rectangle With {.Width = 10, .Height = 10}
Select Case shape
Case r As Rectangle When r.Width = r.Height
Console.WriteLine("Square of {0}", r.Width)
Case r As Rectangle
Console.WriteLine("Rectangle of {0},{1}", r.Width, r.Height)
Case c As Circle
Console.WriteLine("Circle of {0}", c.Radius)
End Select
End Sub
The functionality is still quite limited and quite verbose in comparison to say F# or Scala, but I feel it’s definitely an interesting development for VB.Net.
For comparison here’s an equivalent F# version using discriminated unions:
type Shape =
| Rectangle of width:int * height:int
| Circle of radius:int
let shape = Rectangle(10,10)
match shape with
| Rectangle(w,h) when w=h -> printfn "Square %d" w
| Rectangle(w,h) -> printfn "Rectangle %d, %d" w h
| Circle(r) -> printfn "Circle %d" r
Eval
Pattern matching can be really useful when writing compilers, here’s a simple expression tree evaluator in F#:
type Expression =
| Factor of value:int
| Add of lhs:Expression * rhs:Expression
let rec eval e =
match e with
| Factor(x) -> x
| Add(l,r) -> eval l + eval r
let onePlusOne = Add(Factor(1),Factor(1))
VB.Net vNext can approximate this, albeit in a rather more verbose way:
Public MustInherit Class Expression
End Class
Public Class Factor
Inherits Expression
Public Property Value As Integer
Sub New(x As Integer)
Value = x
End Sub
End Class
Public Class Op
Inherits Expression
Public Property Lhs As Expression
Public Property Rhs As Expression
End Class
Public Class Add
Inherits Op
End Class
Function Eval(e As Expression) As Integer
Select Case e
Case x As Factor
Return x.Value
Case op As Add
Return Eval(op.Lhs) + Eval(op.Rhs)
Case Else
Throw New InvalidOperationException
End Select
End Function
Sub Main()
Dim onePlusOne As Expression =
New Add With {.Lhs = New Factor(1), .Rhs = New Factor(1)}
Console.WriteLine(Eval(onePlusOne))
End Sub
Summary
It will be interesting to see how VB.Net vNext develops. I think first-class support for tuples could be an interesting next step for the language.