Generic types and methods take type parameters written after Of in brackets (List(Of String), Dictionary(Of K, V)); VB writes the brackets as ordinary parentheses, not angle brackets. Delegates and lambdas are the language’s function values.
Generic types and methods
Public Class Box(Of T As Structure)
Public Value As T
End Class
Public Class Repository(Of TKey As IComparable(Of TKey), TItem As {Class, New})
Private ReadOnly _items As New Dictionary(Of TKey, TItem)
Public Function Create(key As TKey) As TItem
Dim item As New TItem
_items(key) = item
Return item
End Function
End Class
Public Function MaxOf(Of T As IComparable(Of T))(a As T, b As T) As T
Return If(a.CompareTo(b) >= 0, a, b)
End Function
Public Delegate Function Mapper(Of TIn, TOut)(value As TIn) As TOut
Dim same = MaxOf(3, 4) ' T is inferred as Integer
Dim bx As New Box(Of Integer) With {.Value = 3}
Constraints follow As after a type parameter: one constraint, or several in braces {Class, New}. The kinds are Class (a reference type), Structure (a value type), New (a public parameterless constructor), a base class, and any number of interfaces; a constraint may mention the type parameter itself (IComparable(Of TKey)). Since version 17.13 the compiler also recognises the unmanaged constraint. A Nothing value of a type parameter is that type’s default.
Variance: on an interface or delegate, Out T (covariant, T only in results) and In T (contravariant, T only in parameters) let a IProducer(Of Dog) be used as a IProducer(Of Animal) and an IConsumer(Of Animal) as an IConsumer(Of Dog) (version 10).
Public Interface IProducer(Of Out T)
Function [Get]() As T
End Interface
Public Interface IConsumer(Of In T)
Sub Take(value As T)
End Interface
Get is escaped because it is a reserved word.Lambdas and delegates
Dim twice As Func(Of Integer, Integer) = Function(x) x * 2
Dim add = Function(a As Integer, b As Integer) a + b
Dim show As Action(Of String) = Sub(s) Console.WriteLine(s)
Dim multi = Function(x As Integer) As Integer
Dim y = x + 1
Return y * y
End Function
Dim counter = 0
Dim inc = Sub() counter += 1 ' closure over a local
inc() : inc()
names.Sort(Function(p, q) String.Compare(p, q))
Dim mapper As Mapper(Of Integer, String) = Function(i) i.ToString()
- A lambda expression is
Function(parameters) expression(the value of the expression is returned) orSub(parameters) statement. A multi-line lambda has statements and ends withEnd FunctionorEnd Sub(version 10); it can declareAsyncandIteratortoo. Parameter types may be left out when the target type gives them. - A lambda closes over the locals and parameters it uses: closures over one local share that one variable (not a copy), so
counterabove is 2 after the two calls. - A delegate is a typed reference to a method: declared with
Delegate SuborDelegate Function(see classes), or taken from the library (Func(Of …)returns a value,Action(Of …)returns nothing,Predicate(Of T)returns a Boolean,EventHandler). It is created withAddressOf Method, a lambda orNew Handler(AddressOf Method), and called like a procedure (twice(2)) or with.Invoke. - Relaxed delegate conversion: the method or lambda may omit parameters or take less specific ones than the delegate has, and a
Functionmay be used for a delegate whose result is dropped. - A lambda that is converted to an
Expression(Of Func(…))becomes an expression tree that library code (LINQ providers) can read; query expressions use the same lambdas (see LINQ).
Not described
Known, not yet covered
- Reference: the full rules of type inference for generic methods, the dominant-type rules, delegate relaxation, closure capture of loop variables and expression-tree restrictions are in the specification (generic types, lambda expressions and closures) and are only outlined.
See also
- Query expressions (LINQ) – lambdas written as queries
- Procedures and events –
AddressOf,AddHandlerand event delegates