Imports System
Imports System.Collections.Generic
Imports System.Runtime.CompilerServices

'Public NotInheritable Class CPersona
'  Private _nombre As String
'  Private _fechaNac As DateTime

'  Public Property Nombre() As String
'    Get
'      Return _nombre
'    End Get
'    Set(value As String)
'      _nombre = value
'    End Set
'  End Property

'  Public Property FechaNac() As DateTime
'    Get
'      Return _fechaNac
'    End Get
'    Set(value As DateTime)
'      _fechaNac = value
'    End Set
'  End Property
'End Class

' Delegado
Public Delegate Function ExprCondicional(pers As CPersona) As Boolean

' Propiedades autoimplementadas a partir de VB 10
Public NotInheritable Class CPersona
  Public Property Nombre() As String
  Public Property FechaNac() As DateTime

  'Public Shared Sub NacidosAño(lista As List(Of CPersona), _
  '                             condición As ExprCondicional)
  '  For Each p In lista
  '    If (condición(p)) Then
  '      Console.WriteLine(p.Nombre)
  '    End If
  '  Next
  'End Sub

  'Public Shared Sub NacidosAño(lista As List(Of CPersona), condición As Func(Of CPersona, Boolean))
  '  For Each p As CPersona In lista
  '    If condición(p) Then
  '      Console.WriteLine(p.Nombre)
  '    End If
  '  Next
  'End Sub
End Class

Module Test

  <Extension()> _
  Function Edad(persona As CPersona) As Integer
    Dim _edad As Integer = DateTime.Today.Year - persona.FechaNac.Year

    If (DateTime.Today.Month > persona.FechaNac.Month Or _
        DateTime.Today.Month = persona.FechaNac.Month And _
        DateTime.Today.Day >= persona.FechaNac.Day) Then
      Return _edad
    Else
      Return _edad - 1
    End If
  End Function

  Public Function Comparar(pers As CPersona) As Boolean
    Return pers.FechaNac.Year = 1991
  End Function

  Sub Main()

    'Dim e = 0 ' equivale a Dim e As Integer = 0
    'Console.WriteLine(e.GetType().FullName) ' imprime: System.Int32

    'Dim m() = {1, 2, 3} ' equivale a Dim m() As Object = {1, 2, 3}
    'For Each a In m
    '  Console.WriteLine(a) ' imprime: 1 2 3
    'Next
    'Console.WriteLine(m.GetType().FullName) ' imprime: System.Object[]

    'Dim persona = New With {.Nombre = "Elena", .Edad = 24}
    'Console.WriteLine(persona.Nombre)
    'Console.WriteLine(persona.GetType().FullName)

    'Dim persona = New CPersona With {.Nombre = "Isabella", _
    '                    .FechaNac = New DateTime(2011, 11, 7)}

    Dim listPersona = New List(Of CPersona)()
    listPersona.AddRange(New CPersona() { _
      New CPersona With { _
        .Nombre = "Isabella", .FechaNac = New DateTime(2011, 11, 7)}, _
      New CPersona With { _
        .Nombre = "Manuel", .FechaNac = New DateTime(1991, 7, 26)} _
     })

    'Dim listPersona = New List(Of CPersona) From { _
    '  New CPersona With { _
    '    .Nombre = "Isabella", .FechaNac = New DateTime(2011, 11, 7)}, _
    '  New CPersona With { _
    '    .Nombre = "Manuel", .FechaNac = New DateTime(1991, 7, 26)} _
    '} ' a partir de VB 2010

    For Each persona In listPersona
      'Console.WriteLine("{0}, {1}", persona.Nombre, Test.Edad(persona))
      Console.WriteLine("{0}, {1}", persona.Nombre, persona.Edad())
    Next

    'Dim expLambda1 = Function(a) a * 2 ' expresión; tipo implícito
    'Dim expLambda2 = Function(a As Integer) a * 2 ' expresión; tipo explícito
    'Dim expLambda3 = Function(a, b) a + b ' varios parámetros
    'Dim expLambda4 = Function() Math.Sqrt(2) ' sin parámetros
    'Dim expLambda5 = Function(s As String, x As Integer) s.Length > x ' varios parámetros con tipo
    'Console.WriteLine(expLambda1(7))
    'Console.WriteLine(expLambda2(7))
    'Console.WriteLine(expLambda3(5, 8))
    'Console.WriteLine(expLambda4())
    'Console.WriteLine(expLambda5("Hola", 4))

    'Dim exprLambda = Function(a)
    '                   Return a * 2
    '                 End Sub ' a partir de VB 2010
    'Dim exprLambda = Function(a As Integer)
    '                   If (a > 2) Then a = 10
    '                   Return a + 2
    '                 End Function ' a partir de VB 2010
    'Dim exprLambda = Sub() Console.WriteLine("hola") ' a partir de VB 2010
    'exprLambda()

    'Dim delegado As ExprCondicional = AddressOf Comparar
    'CPersona.NacidosAño(listPersona, delegado)

    'Dim métodoAnónimo As ExprCondicional = Function(p As CPersona) p.FechaNac.Year = 1991
    'CPersona.NacidosAño(listPersona, métodoAnónimo)
    'CPersona.NacidosAño(listPersona, _
    '                    Function(p) p.FechaNac.Year = 1991)

    'Dim esPar As Func(Of Integer, Boolean) = Function(n) n Mod 2 = 0
    'Dim resultado As Boolean = esPar(11)
    'Console.WriteLine(resultado)

    'Dim esNacidoEnAño As Func(Of CPersona, Integer, Boolean) = Function(p, año) p.FechaNac.Year = año
    'For Each p As CPersona In listPersona
    '  If esNacidoEnAño(p, 1991) Then
    '    Console.WriteLine(p.Nombre)
    '  End If
    'Next

    'Dim números As Integer() = {6, 7, 11, 9, 8, 5, 4, 1, 3, 2}
    'Dim númerosPares As Integer = números.Count(Function(n) n Mod 2 = 0)
    'Console.WriteLine(númerosPares) ' resultado: 4

    Dim números As Integer() = {6, 7, 11, 9, 8, 5, 4, 1, 3, 2}
    Dim primerosNumsMenoresQue9 = números.TakeWhile(Function(n As Integer) n < 9)
    For Each n In primerosNumsMenoresQue9
      Console.WriteLine(n)
    Next

    'Dim numsImparesOrdenados = _
    '      From n In números _
    '      Where (n Mod 2 <> 0) _
    '      Order By n _
    '      Select n ' resultado: 1, 3, 5, 7, 9, 11

    'Dim numsImparesOrdenados = números.Where( _
    '  Function(n) n Mod 2 <> 0).OrderBy( _
    '  Function(n) n).Select(Function(n) n)

    Dim numsImparesOrdenados = números. _
          Where(Function(n) n Mod 2 <> 0). _
          OrderBy(Function(n) n). _
          Select(Function(n) n)

    For Each n In numsImparesOrdenados
      Console.WriteLine(n)
    Next

  End Sub
End Module
