Skip to content

2. Fundamentos del lenguaje VB.NET

2.1. Introducción

Tratamos VB.NET en primer lugar como un lenguaje de programación clásico. Abordaremos los objetos más adelante.

En un programa hay dos cosas

  • datos
  • las instrucciones que los manipulan

Por lo general, se intenta separar los datos de las instrucciones:

2.2. Los datos de VB.NET

VB.NET utiliza los siguientes tipos de datos:

  1. números enteros, reales y decimales
  2. caracteres y cadenas de caracteres
  3. booleanos
  4. fechas
  5. objetos

2.2.1. Los tipos de datos predefinidos

Tipo VB
Tipo .NET equivalente
Tamaño
Rango de valores
Booleano
System.Boolean
2 bytes
True o False.
Byte
System.Byte
1 byte
0 a 255 (sin signo).
Caracter
System.Char
2 bytes
0 a 65 535 (sin signo).
Fecha
System.DateTime
8 bytes
0:00:00 del 1 de enero de 0001 a las 23:59:59 del 31 de diciembre de 9999.
Decimal
System.Decimal
16 bytes
De 0 a +/-79 228 162 514 264 337 593 543 950 335 sin decimales; de 0 a +/-7,9228162514264337593543950335 con 28 decimales; el número más pequeño distinto de cero es +/-0,0000000000000000000000000001 (+/-1E-28).
Doble
System.Double
8 bytes
-1,79769313486231E+308 a
-4,94065645841247E-324 para los valores negativos; 4,94065645841247E-324 a 1,79769313486231E+308 para los valores positivos.
Integer
System.Int32
4 bytes
-2 147 483 648 a 2 147 483 647.
Long
System.Int64
8 bytes
-9 223 372 036 854 775 808 a 9 223 372 036 854 775 807.
Objeto
System.Object
4 bytes
En una variable de tipo Object se puede almacenar cualquier tipo.
Short
System.Int16
2 bytes
-32 768 a 32 767.
Single
System.Single
4 bytes
-3,402823E+38 a -1,401298E-45 para los valores negativos; 1,401298E-45 a 3,402823E+38 para los valores positivos.
Cadena
System.String (clase)
 
De 0 a aproximadamente 2000 millones de caracteres Unicode.

En la tabla anterior, se observa que hay dos tipos posibles para un entero de 32 bits: Integer y System.Int32. Ambos tipos son intercambiables. Lo mismo ocurre con los demás tipos VB y sus equivalentes en la plataforma .NET. A continuación se muestra un ejemplo de programa:


Module types
    Sub Main()
        ' números enteros
        Dim var1 As Integer = 100
        Dim var2 As Long = 10000000000L
        Dim var3 As Byte = 100
        Dim var4 As Short = 4
        ' números reales
        Dim var5 As Decimal = 4.56789D
        Dim var6 As Double = 3.4
        Dim var7 As Single = -0.000103F
        ' fecha
        Dim var8 As Date = New Date(2003, 1, 1, 12, 8, 4)
        ' booleano
        Dim var9 As Boolean = True
        ' carácter
        Dim var10 As Char = "A"c
        ' cadena de caracteres
        Dim var11 As String = "abcde"
        ' objeto
        Dim var12 As Object = New Object
        ' visualizaciones
        Console.Out.WriteLine("var1=" + var1.ToString)
        Console.Out.WriteLine("var2=" + var2.ToString)
        Console.Out.WriteLine("var3=" + var3.ToString)
        Console.Out.WriteLine("var4=" + var4.ToString)
        Console.Out.WriteLine("var5=" + var5.ToString)
        Console.Out.WriteLine("var6=" + var6.ToString)
        Console.Out.WriteLine("var7=" + var7.ToString)
        Console.Out.WriteLine("var8=" + var8.ToString)
        Console.Out.WriteLine("var9=" + var9.ToString)
        Console.Out.WriteLine("var10=" + var10)
        Console.Out.WriteLine("var11=" + var11)
        Console.Out.WriteLine("var12=" + var12.ToString)
    End Sub
End Module

La ejecución da los siguientes resultados:

var1=100
var2=10000000000
var3=100
var4=4
var5=4,56789
var6=3,4
var7=-0,000103
var8=01/01/2003 12:08:04
var9=True
var10=A
var11=abcde
var12=System.Object

2.2.2. Notación de datos literales

Integer
145, -7, &FF (hexadecimal)
Long
100000L
Double
134,789, -45E-18 (-45 × 10⁻¹⁸)
Single
134.789F, -45E-18F (-45 10-18)
Decimal
100000D
Char
"A"c
String
"hoy"
Boolean
verdadero, falso
date
New Date(2003, 1, 1) para el 01/01/2003

Cabe destacar los siguientes puntos:

  • 100000L, la L significa que se considera el número como un entero largo
  • 134.789F, la F significa que se considera el número como un real de precisión simple
  • 100000D, la D significa que se considera el número como un número real decimal
  • "A"c, para convertir la cadena de caracteres "A" en el carácter 'A'
  • la cadena de caracteres está rodeada por el carácter ". Si la cadena debe contener el carácter ", se duplica este como en "abcd""e" para representar la cadena [abcd"e].

2.2.3. Declaración de datos

2.2.3.1. Función de las declaraciones

Un programa manipula datos caracterizados por un nombre y un tipo. Estos datos se almacenan en memoria. En el momento de la traducción del programa, el compilador asigna a cada dato una ubicación en memoria caracterizada por una dirección y un tamaño. Lo hace con la ayuda de las declaraciones realizadas por el programador. Además, estas permiten al compilador detectar errores de programación. Así, la operación x=x*2 se declarará errónea si x es una cadena de caracteres, por ejemplo.

2.2.3.2. Declaración de constantes

La sintaxis para declarar una constante es la siguiente:

const identificador as tipo=valor

por ejemplo, [const PI as double=3.141592]. ¿Por qué declarar constantes?

  1. La lectura del programa será más fácil si se le da a la constante un nombre significativo: [const taux_tva as single=0.186F]
  2. La modificación del programa será más fácil si la «constante» llega a cambiar. Así, en el caso anterior, si el tipo de IVA pasa al 33 %, la única modificación que habrá que hacer será cambiar la instrucción que define su valor: [const taux_tva as single=0.336F]. Si se hubiera utilizado 0,186 explícitamente en el programa, habría que modificar numerosas instrucciones.

2.2.3.3. Declaración de variables

Una variable se identifica mediante un nombre y se asocia a un tipo de datos. VB.NET no distingue entre mayúsculas y minúsculas. Por lo tanto, las variables FIN y fin son idénticas. Las variables pueden inicializarse al declararlas. La sintaxis para declarar una o varias variables es:

dim variable1,variable2,...,variablen as identificador_de_tipo

donde identificateur_de_type es un tipo predefinido o un tipo definido por el programador.

2.2.4. Las conversiones entre números y cadenas de caracteres

nombre -> chaîne
nombre.ToString o "" & número o CType(número,String)
objet -> chaîne
objet.ToString
chaine -> Integer
Integer.Parse(cadena) o Int32.Parse
chaîne -> Long
Long.Parse (cadena) o Int64.Parse
chaîne -> Double
Double.Parse (cadena)
chaîne -> Single
Single.Parse(cadena)

La conversión de una cadena a un número puede fallar si la cadena no representa un número válido. En ese caso, se genera un error fatal denominado excepción en VB.NET. Este error se puede gestionar mediante la siguiente cláusula try/catch:

try
        appel de la fonction susceptible de générer l'exception
 catch e as Exception
        traiter l'exception e
end try
instruction suivante

Si la función no genera una excepción, se pasa a la siguiente instrucción; de lo contrario, se pasa al cuerpo de la cláusula catch y, a continuación, a la siguiente instrucción. Más adelante volveremos sobre la gestión de excepciones. A continuación se muestra un programa que presenta las principales técnicas de conversión entre números y cadenas de caracteres. En este ejemplo, la función muestra en pantalla el valor de su parámetro. Así, affiche(S) muestra el valor de S en pantalla.


' directivas
Option Strict On

' espacios de nombres importados
Imports System

' el módulo de prueba
Module Module1

    Sub Main()
        ' procedimiento principal
        ' datos locales
        Dim S As String
        Const i As Integer = 10
        Const l As Long = 100000
        Const f As Single = 45.78F
        Dim d As Double = -14.98

        ' número --> cadena
        affiche(CType(i, String))
        affiche(CType(l, String))
        affiche(CType(f, String))
        affiche(CType(d, String))

        'booleano --> cadena
        Const b As Boolean = False
        affiche(b.ToString)

        ' cadena --> entero
        Dim i1 As Integer = Integer.Parse("10")
        affiche(i1.ToString)
        Try
            i1 = Integer.Parse("10.67")
            affiche(i1.ToString)
        Catch e As Exception
            affiche("Erreur [10.67] : " + e.Message)
        End Try

        ' cadena --> entero largo
        Dim l1 As Long = Long.Parse("100")
        affiche("" + l1.ToString)
        Try
            l1 = Long.Parse("10.675")
            affiche("" & l1)
        Catch e As Exception
            affiche("Erreur [10.675] : " + e.Message)
        End Try

        ' cadena --> doble
        Dim d1 As Double = Double.Parse("100,87")
        affiche(d1.ToString)
        Try
            d1 = Double.Parse("abcd")
            affiche("" & d1)
        Catch e As Exception
            affiche("Erreur [abcd] : " + e.Message)
        End Try

        ' cadena --> single
        Dim f1 As Single = Single.Parse("100,87")
        affiche(f1.ToString)
        Try
            d1 = Single.Parse("abcd")
            affiche(f1.ToString)
        Catch e As Exception
            affiche("Erreur [abcd] : " + e.Message)
        End Try
    End Sub

    ' muestra
    Public Sub affiche(ByVal S As String)
        Console.Out.WriteLine("S=" + S)
    End Sub
End Module

Los resultados obtenidos son los siguientes:

S=10
S=100000
S=45,78
S=-14,98
S=False
S=10
S=Erreur [10.67] : Le format de la chaîne d'entrée est incorrect.
S=100
S=Erreur [10.675] : Le format de la chaîne d'entrée est incorrect.
S=100,87
S=Erreur [abcd] : Le format de la chaîne d'entrée est incorrect.
S=100,87
S=Erreur [abcd] : Le format de la chaîne d'entrée est incorrect.

Cabe señalar que los números reales en forma de cadena de caracteres deben utilizar la coma y no el punto decimal. Por lo tanto, se escribirá Dim d As Double = -14.98 pero Dim d1 As Double = Double.Parse("100,87")

2.2.5. Las matrices de datos

Una matriz VB.NET es un objeto que permite agrupar bajo un mismo identificador datos del mismo tipo. Su declaración es la siguiente:

Dim Tabla(n) as tipo o Dim Tabla() as tipo = New tipo(n) {}

donde n es el índice del último elemento de la matriz. La sintaxis Tableau(i) designa el dato n.º i donde i pertenece al intervalo [0,n]. Cualquier referencia al dato Tableau(i) donde i no pertenezca al intervalo [0,n] provocará una excepción. Una matriz puede inicializarse al mismo tiempo que se declara. En este caso, no es necesario indicar el número del último elemento.


        Dim entiers() As Integer = {0, 10, 20, 30}

Las matrices tienen una propiedad «Length» que indica el número de elementos de la matriz. A continuación se muestra un programa de ejemplo:


Module tab0
    Sub Main()
        ' una primera tabla
        Dim tab0(5) As Integer
        For i As Integer = 0 To UBound(tab0)
            tab0(i) = i
        Next
        For i As Integer = 0 To UBound(tab0)
            Console.Out.WriteLine("tab0(" + i.ToString + ")=" + tab0(i).tostring)
        Next

        ' un segundo cuadro
        Dim tab1() As Integer = New Integer(5) {}
        For i As Integer = 0 To tab1.Length - 1
            tab1(i) = i * 10
        Next
        For i As Integer = 0 To tab1.Length - 1
            Console.Out.WriteLine("tab1(" + i.ToString + ")=" + tab1(i).tostring)
        Next
    End Sub
End Module

y su ejecución:

tab0(0)=0
tab0(1)=1
tab0(2)=2
tab0(3)=3
tab0(4)=4
tab0(5)=5
tab1(0)=0
tab1(1)=10
tab1(2)=20
tab1(3)=30
tab1(4)=40
tab1(5)=50

Una matriz bidimensional se puede declarar de la siguiente manera:

Dim Tabla(n,m) as Tipo o Dim Tabla(,) as Tipo = New Tipo(n,m) {}

donde n+1 es el número de filas y m+1 el número de columnas. La sintaxis Tableau(i,j) designa el elemento j de la fila i de Tableau. La matriz bidimensional también se puede inicializar al mismo tiempo que se declara:


        Dim réels(,) As Double = {{0.5, 1.7}, {8.4, -6}}

El número de elementos en cada una de las dimensiones se puede obtener mediante el método GetLenth(i), donde i=0 representa la dimensión correspondiente al primer índice, i=1 la dimensión correspondiente al segundo índice, … A continuación se muestra un programa de ejemplo:


Module Module2
    Sub Main()
        ' una primera tabla
        Dim tab0(2, 1) As Integer
        For i As Integer = 0 To UBound(tab0)
            For j As Integer = 0 To tab0.GetLength(1) - 1
                tab0(i, j) = i * 10 + j
            Next
        Next
        For i As Integer = 0 To UBound(tab0)
            For j As Integer = 0 To tab0.GetLength(1) - 1
                Console.Out.WriteLine("tab0(" + i.ToString + "," + j.ToString + ")=" + tab0(i, j).tostring)
            Next
        Next

        ' un segundo cuadro
        Dim tab1(,) As Integer = New Integer(2, 1) {}
        For i As Integer = 0 To tab1.GetLength(0) - 1
            For j As Integer = 0 To tab1.GetLength(1) - 1
                tab1(i, j) = i * 100 + j
            Next
        Next
        For i As Integer = 0 To tab1.GetLength(0) - 1
            For j As Integer = 0 To tab1.GetLength(1) - 1
                Console.Out.WriteLine("tab1(" + i.ToString + "," + j.ToString + ")=" + tab1(i, j).tostring)
            Next
        Next
    End Sub
End Module

y los resultados de su ejecución:

tab0(0)=0
tab0(1)=1
tab0(2)=2
tab0(3)=3
tab0(4)=4
tab0(5)=5
tab1(0)=0
tab1(1)=10
tab1(2)=20
tab1(3)=30
tab1(4)=40
tab1(5)=50

Una matriz de matrices se declara de la siguiente manera:

Dim Matriz(n)() as Tipo o Dim Matriz()() as Tipo = new Tipo(n)()

La declaración anterior crea una matriz de n+1 filas. Cada elemento Tableau(i) es una referencia de matriz unidimensional. Estas matrices no se crean durante la declaración anterior. El siguiente ejemplo ilustra la creación de una matriz de matrices:


        ' una matriz de matrices
        Dim noms()() As String = New String(3)() {}
        ' inicialización
        For i = 0 To noms.Length - 1
            noms(i) = New String(i) {}
            For j = 0 To noms(i).Length - 1
                noms(i)(j) = "nom" & i & j
            Next
        Next

Aquí, noms(i) es una matriz de i+1 elementos. Como noms(i) es una matriz, noms(i).Length es su número de elementos. A continuación se muestra un ejemplo que agrupa los tres tipos de matrices que acabamos de presentar:


' instrucciones
Option Strict On
Option Explicit On 

' importaciones
Imports System

' clase de prueba
Module test
    Sub main()
        ' una matriz unidimensional inicializada
        Dim entiers() As Integer = {0, 10, 20, 30}
        Dim i As Integer
        For i = 0 To entiers.Length - 1
            Console.Out.WriteLine("entiers[" & i & "]=" & entiers(i))
        Next

        ' una matriz bidimensional inicializada
        Dim réels(,) As Double = {{0.5, 1.7}, {8.4, -6}}
        Dim j As Integer
        For i = 0 To réels.GetLength(0) - 1
            For j = 0 To réels.GetLength(1) - 1
                Console.Out.WriteLine("réels[" & i & "," & j & "]=" & réels(i, j))
            Next
        Next

        ' una matriz de matrices
        Dim noms()() As String = New String(3)() {}

        ' inicialización
        For i = 0 To noms.Length°- 1
            noms(i) =°New String(i) {}
            For j = 0 To noms(i).Length - 1
                noms(i)(j) = "nom" & i & j
            Next
        Next

        ' visualización
        For i = 0 To noms.Length°- 1
            For j = 0 To noms(i).Length - 1
                Console.Out.WriteLine("noms[" & i & "][" & j & "]=" & noms(i)(j))
            Next
        Next
    End Sub
End Module

Al ejecutarlo, obtenemos los siguientes resultados:

entiers[0]=0
entiers[1]=10
entiers[2]=20
entiers[3]=30
réels[0,0]=0,5
réels[0,1]=1,7
réels[1,0]=8,4
réels[1,1]=-6
noms[0][0]=nom00
noms[1][0]=nom10
noms[1][1]=nom11
noms[2][0]=nom20
noms[2][1]=nom21
noms[2][2]=nom22
noms[3][0]=nom30
noms[3][1]=nom31
noms[3][2]=nom32
noms[3][3]=nom33

2.3. Las instrucciones básicas de VB.NET

Se distingue

1 las instrucciones elementales ejecutadas por el ordenador.

2 las instrucciones de control del desarrollo del programa.

Las instrucciones elementales se aprecian claramente al examinar la estructura de un microordenador y sus periféricos.

  1. Lectura de información procedente del teclado

  2. procesamiento de información

  3. Escritura de información en la pantalla

  4. Lectura de información procedente de un archivo en disco

  5. Escritura de información en un archivo de disco

2.3.1. Escritura en pantalla

Existen diferentes instrucciones para escribir en pantalla:

Console.Out.WriteLine(expression)
Console.WriteLine(expression)
Console.Error.WriteLine (expression)

donde expression es cualquier tipo de dato que pueda convertirse en una cadena de caracteres para mostrarse en pantalla. En los ejemplos vistos hasta ahora, solo hemos utilizado la instrucción Console.Out.WriteLine(expresión).

La clase System.Console da acceso a las operaciones de escritura en pantalla (Write, WriteLine). La clase Console tiene dos propiedades, Out y Error, que son flujos de escritura de tipo StreamWriter:

  • Console.WriteLine() es equivalente a Console.Out.WriteLine() y escribe en el flujo Out, normalmente asociado a la pantalla.
  • Console.Error.WriteLine() escribe en el flujo Error, que también suele estar asociado a la pantalla.

Los flujos Out y Error están asociados por defecto a la pantalla. Pero pueden redirigirse a archivos de texto en el momento de la ejecución del programa, como veremos a continuación.

2.3.2. Lectura de datos introducidos mediante el teclado

El flujo de datos procedente del teclado se designa mediante el objeto Console.In de tipo StreamReader. Este tipo de objetos permite leer una línea de texto con el método ReadLine:


        Dim ligne As String = Console.In.ReadLine()

La línea introducida mediante el teclado se almacena en la variable ligne y, a continuación, puede ser procesada por el flujo programme.Le. El flujo de entrada puede redirigirse a un archivo, al igual que los flujos de salida y de error.

2.3.3. Ejemplo de entradas y salidas

A continuación se muestra un breve programa que ilustra las operaciones de entrada-salida de teclado/pantalla:


' opciones
Option Explicit On 
Option Strict On

' espacios de nombres
Imports System

' módulo
Module io1
    Sub Main()
        ' escritura en el flujo Out
        Dim obj As New Object
        Console.Out.WriteLine(("" & obj.ToString))

        ' escritura en el flujo Error
        Dim i As Integer = 10
        Console.Error.WriteLine(("i=" & i))

        ' lectura de una línea introducida mediante el teclado
        Console.Out.Write("Tapez une ligne : ")
        Dim ligne As String = Console.In.ReadLine()
        Console.Out.WriteLine(("ligne=" + ligne))
    End Sub
End Module

y los resultados de la ejecución:

System.Object
i=10
Tapez une ligne : ceci est un essai
ligne=ceci est un essai

Las instrucciones


        Dim obj As New Object
        Console.Out.WriteLine(obj.ToString)

solo sirven para mostrar que cualquier objeto puede ser objeto de una visualización. No vamos a explicar aquí el significado de lo que se muestra.

2.3.4. Redirección de E/S

En DOS/Windows existen tres dispositivos estándar denominados:

  1. dispositivo de entrada estándar: designa por defecto el teclado y lleva el n.º 0
  2. dispositivo de salida estándar: designa por defecto la pantalla y lleva el n.º 1
  3. dispositivo de error estándar: designa por defecto la pantalla y lleva el n.º 2

En VB.NET, el flujo de escritura Console.Out escribe en el dispositivo 1, el flujo de escritura Console.Error escribe en el dispositivo 2 y el flujo de lectura Console.In lee los datos procedentes del dispositivo 0. Al ejecutar un programa en una ventana de DOS en Windows, se pueden especificar cuáles serán los dispositivos 0, 1 y 2 para el programa ejecutado. Consideremos la siguiente línea de comando:

pg arg1 arg2 .. argn

Detrás de los argumentos argi del programa pg, se pueden redirigir los dispositivos de E/S estándar a archivos:

0<in.txt
el flujo de entrada estándar n.º 0 se redirige al archivo in.txt. En el programa, el flujo Console.In tomará, por tanto, sus datos del archivo in.txt.
  
1>out.txt
redirige la salida n.º 1 al archivo out.txt. Esto implica que, en el programa, el flujo Console.Out escribirá sus datos en el archivo out.txt
   
1>>out.txt
Lo mismo, pero los datos escritos se añaden al contenido actual del archivo out.txt.
   
2>error.txt
redirige la salida n.º 2 al archivo error.txt. Esto hace que, en el programa, el flujo Console.Error escriba sus datos en el archivo error.txt
   
2>>error.txt
lo mismo, pero los datos escritos se añaden al contenido actual del archivo error.txt.
   
1>out.txt 2>error.txt
Los dispositivos 1 y 2 se redirigen ambos a archivos
   

Cabe señalar que para redirigir los flujos de E/S del programa pg a archivos, no es necesario modificar el programa pg. Es el programa OS el que determina la naturaleza de los dispositivos 0, 1 y 2. Consideremos el siguiente programa:


' opciones
Option Explicit On 
Option Strict On

' espacios de nombres
Imports System

' redireccionamientos
Module console2
    Sub Main()
        ' lectura del flujo In
        Dim data As String = Console.In.ReadLine()
        ' escritura del flujo Out
        Console.Out.WriteLine(("écriture dans flux Out : " + data))
        ' escritura de flujo Error
        Console.Error.WriteLine(("écriture dans flux Error : " + data))
    End Sub
End Module

Compilemos este programa:

dos>vbc es2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
Copyright (C) Microsoft Corporation 1987-2002. Tous droits réservés.

dos>dir
24/02/2004  15:39                  416 es2.vb
11/03/2004  08:20                3 584 es2.exe

Hagamos una primera ejecución:

dos>es2.exe
un premier test
écriture dans flux Out : un premier test
écriture dans flux Error : un premier test

La ejecución anterior no redirige ninguno de los flujos de E/S estándar In, Out, Error. Ahora vamos a redirigir los tres flujos. El flujo In se redirigirá a un archivo in.txt, el flujo Out al archivo out.txt, y el flujo Error al archivo error.txt. Esta redirección se realiza en la línea de comandos de la forma

dos>es2.exe 0<in.txt 1>out.txt 2>error.txt

La ejecución da los siguientes resultados:

dos>more in.txt
un second test

dos>es2.exe 0<in.txt 1>out.txt 2>error.txt

dos>more out.txt
écriture dans flux Out : un second test

dos>more error.txt
écriture dans flux Error : un second test

Se ve claramente que los flujos Out y Error no escriben en los mismos dispositivos.

2.3.5. Asignación del valor de una expresión a una variable

Aquí nos centramos en la operación variable=expresión. La expresión puede ser de tipo: aritmético, relacional, booleano o de caracteres.

2.3.5.1. Lista de operadores

Acción
Elemento del lenguaje
Arithmétique
^, –, *, /, \, Mod, +, =
Assignation
=, ^=, *=, /=, \=, +=, -=, &=
Comparaison
=, <>, <, >, <=, >=, Like, Is
Concaténation
&, +
Opérations logiques/de bits
Not, And, Or, Xor, AndAlso, OrElse
Opérations diverses
AddressOf, GetType

2.3.5.2. Expresión aritmética

Los operadores de las expresiones aritméticas son los siguientes:

Arithmétique
^, –, *, /, \, Mod, +, =

+: suma, -: resta, *: multiplicación, /: división real, \: cociente de la división entera, Mod: resto de la división entera, ^: elevación a una potencia. Así, el siguiente programa:


' operadores aritméticos
Module operateursarithmetiques
    Sub Main()
        Dim i, j As Integer
        i = 4 : j = 3
        Console.Out.WriteLine(i & "/" & j & "=" & (i / j))
        Console.Out.WriteLine(i & "\" & j & "=" & (i \ j))
        Console.Out.WriteLine(i & " mod " & j & "=" & (i Mod j))

        Dim r1, r2 As Double
        r1 = 4.1 : r2 = 3.6
        Console.Out.WriteLine(r1 & "/" & r2 & "=" & (r1 / r2))
        Console.Out.WriteLine(r1 & "^2=" & (r1 ^ 2))
        Console.Out.WriteLine(Math.Cos(3))
    End Sub
End Module

da los siguientes resultados:

4/3=1,33333333333333
4\3=1
4 mod 3=1
4,1/3,6=1,13888888888889
4,1^2=16,81
-0,989992496600445

Existen diversas funciones matemáticas. Estas son algunas de ellas:


Public Shared Function Sqrt(ByVal d As Double ) As Double
raíz cuadrada

[Visual Basic]
Public Shared Function Cos(ByVal d As Double ) As Double
coseno

Public Shared Function Sin(ByVal a As Double) As Double
Senos

[Visual Basic]
Public Shared Function Tan(ByVal a As Double) As Double
Tangente

[Visual Basic]
Public Shared Function Pow(ByVal x As Double,ByVal y As Double) As Double
x elevado a y (x>0)

[Visual Basic]
Public Shared Function Exp(ByVal d As Double) As Double
Exponencial

[Visual Basic]
Overloads Public Shared Function Log( ByVal d As Double ) As Double
Logaritmo natural

Overloads Public Shared Function Abs(ByVal value As Double ) As Double
Valor absoluto
....
 

Todas estas funciones están definidas en una clase .NET llamada Math. Al utilizarlas, hay que anteponerles el nombre de la clase en la que están definidas. Así, se escribirá:

        Dim r1, r2 As Double
        r2 = Math.Sqrt(9)
        r1 = Math.Cos(3)

La definición completa de la clase Math es la siguiente:

E
Representa la base del logaritmo natural especificada por la constante e.
   
PI
Representa la relación entre la circunferencia de un círculo y su diámetro, especificada por la constante π.
   
Abs
Sobrecargada. Devuelve el valor absoluto de un número especificado.
  
Acos
Devuelve el ángulo cuyo coseno es el número especificado.
  
Asin
Devuelve el ángulo cuyo seno es el número especificado.
  
Atan
Devuelve el ángulo cuya tangente es el número especificado.
  
Atan2
Devuelve el ángulo cuya tangente es el cociente de dos números especificados.
  
BigMul
Genera el producto integral de dos números de 32 bits.
  
Ceiling
Devuelve el número entero más pequeño mayor o igual que el número especificado.
  
Cos
Devuelve el coseno del ángulo especificado.
  
Cosh
Devuelve el coseno hiperbólico del ángulo especificado.
  
DivRem
Sobrecargada. Devuelve el cociente de dos números, pasando el resto como parámetro de salida.
  
Exp
Devuelve e elevado a la potencia especificada.
  
Floor
Devuelve el número entero mayor menor o igual que el número especificado.
  
IEEERemainder
Devuelve el resto de la división de un número especificado por otro.
  
Log
Sobrecargada. Devuelve el logaritmo de un número especificado.
  
Log10
Devuelve el logaritmo en base 10 de un número especificado.
  
Max
Sobrecargada. Devuelve el mayor de dos números especificados.
  
Min
Sobrecargada. Devuelve el menor de dos números.
  
Pow
Devuelve un número especificado elevado a la potencia especificada.
  
Round
Sobrecargada. Devuelve el número más cercano al valor especificado.
  
Sign
Sobrecargada. Devuelve un valor que indica el signo de un número.
  
Sin
Devuelve el seno del ángulo especificado.
  
Sinh
Devuelve el seno hiperbólico del ángulo especificado.
  
Sqrt
Devuelve la raíz cuadrada de un número especificado.
  
Tan
Devuelve la tangente del ángulo especificado.
  
Tanh
Devuelve la tangente hiperbólica del ángulo especificado.
  

Cuando se dice que una función está «sobrecargada», significa que existe para distintos tipos de parámetros. Por ejemplo, la función Abs(x) existe para x de tipo Integer, Long, Decimal, Single y Float. Para cada uno de estos tipos hay una definición distinta de la función Abs. Por eso se dice que está sobrecargada.

2.3.5.3. Prioridades en la evaluación de expresiones aritméticas

La prioridad de los operadores al evaluar una expresión aritmética es la siguiente (de mayor a menor prioridad):

Categoría
Operadores
Primaire
Todas las expresiones sin operador: funciones, paréntesis
Élévation à la puissance
^
Négation unaire
+, -
Multiplication
*, /
Division par un entier
\
Modulo
Mod
Addition
+, -

2.3.5.4. Expresiones relacionales

Los operadores son los siguientes:

Comparaison
=, <>, <, >, <=, >=, Like, Is

=: igual a, <>: diferente de, <: menor que (estricto), >: mayor que (estricto), <=: menor o igual, >=: mayor o igual, Like: coincide con un patrón, Is: identidad de objetos. Todos estos operadores tienen la misma prioridad. Se evalúan de izquierda a derecha. El resultado de una expresión relacional es un valor booleano.

Comparación de cadenas de caracteres: consideremos el siguiente programa:


' espacios de nombres
Imports System

Module string1
    Sub main()
        Dim ch1 As Char = "A"c
        Dim ch2 As Char = "B"c
        Dim ch3 As Char = "a"c
        Console.Out.WriteLine("A<B=" & (ch1 < ch2))
        Console.Out.WriteLine("A<a=" & (ch1 < ch3))
        Dim chat As String = "chat"
        Dim chien As String = "chien"
        Dim chaton As String = "chaton"
        Dim chat2 As String = "CHAT"
        Console.Out.WriteLine("chat<chien=" & (chat < chien))
        Console.Out.WriteLine("chat<chaton=" & (chat < chaton))
        Console.Out.WriteLine("chat<CHAT=" & (chat < chat2))
        Console.Out.WriteLine("chaton like chat*=" & ("chaton" Like "chat*"))
    End Sub
End Module

y el resultado de su ejecución:

A<B=True
A<a=True
chat<chien=True
chat<chaton=True
chat<CHAT=False
chaton like chat*=True

Supongamos que tenemos dos caracteres C1 y C2. Es posible compararlos con los operadores: <, <=, =, <>, >, >=. En este caso, lo que se compara son los valores Unicode de los caracteres, que son números. Según el orden Unicode, se dan las siguientes relaciones:

espacio < .. < '0' < '1' < .. < '9' < .. < 'A' < 'B' < .. < 'Z' < .. < 'a' < 'b' < .. <'z'

Las cadenas de caracteres se comparan carácter por carácter. La primera desigualdad que se encuentra entre dos caracteres implica una desigualdad en el mismo sentido en las cadenas. Con estas explicaciones, se invita al lector a estudiar los resultados del programa anterior.

2.3.5.5. Expresiones booleanas

Los operadores son los siguientes:

Opérations logiques/de bits
Not, And, Or, Xor, AndAlso, OrElse

Not: y lógico, Or: o lógico, Not: negación, Xor: o exclusivo.

op1 AndAlso op2: si op1 es falso, op2 no se evalúa y el resultado es falso.

op1 OrElse op2: si op1 es verdadero, op2 no se evalúa y el resultado es verdadero.

La prioridad de estos operadores entre sí es la siguiente:

NOT logique
Not
AND logique
And, AndAlso
OR logique
O bien, OrElse
XOR logique
XOR

El resultado de una expresión booleana es un valor booleano.

2.3.5.6. Operaciones con bits

Por un lado, encontramos los mismos operadores que los booleanos, con la misma prioridad. También hay dos operadores de desplazamiento: << y >>. Sean i y j dos enteros.

i<<n
desplaza i n bits a la izquierda. Los bits entrantes son ceros.
i>>n
desplaza i n bits a la derecha. Si i es un entero con signo (signed char, int, long), se conserva el bit de signo.
i & j
realiza la operación lógica ET entre i y j bit a bit.
i | j
realiza la operación lógica bit a bit de i y j.
~i
complementa i a 1
i^j
realiza la operación OU EXCLUSIF de i y j

Sea el siguiente programa:


Module operationsbit
    Sub main()
        ' manipulación de bits
        Dim i As Short = &H123F
        Dim k As Short = &H7123
        Console.Out.WriteLine("i<<4=" & (i << 4).ToString("X"))
        Console.Out.WriteLine("i>>4=" & (i >> 4).ToString("X"))
        Console.Out.WriteLine("k>>4=" & (k >> 4).ToString("X"))
        Console.Out.WriteLine("i and 4=" & (i And 4).ToString("X"))
        Console.Out.WriteLine("i or 4 =" & (i Or 4).ToString("X"))
        Console.Out.WriteLine("not i=" & (Not i).ToString("X"))
    End Sub
End Module

Su ejecución da los siguientes resultados:

i<<4=23F0
i>>4=123
k>>4=712
i and 4=4
i or k =123F
not i=EDC0

2.3.5.7. Operador asociado a una asignación

Es posible escribir a+=b, lo que significa a=a+b. La lista de operadores que se pueden combinar con la operación de asignación es la siguiente:

combinaison d'opérateurs
^=, *=, /=, \=, +=, -=, &=

2.3.5.8. Prioridad general de los operadores

Categoría
Operadores
Primaire
Todas las expresiones sin operador
Élévation à la puissance
^
Négation unaire
+, -
Multiplication
*, /
Division par un entier
\
Modulo
Mod
Addition
+, -
Concaténation
&
Déplacement
<<, >>
Relationnel
=, <>, <, >, <=, >=, Like, Is, TypeOf...Is
NOT logique
Not
AND logique
Y, AndAlso
OR logique
O bien, OrElse
XOR logique
XOR

Cuando un operando se coloca entre dos operadores de la misma prioridad, la asociatividad de los operadores determina el orden en que se realizan las operaciones. Todos los operadores son asociativos por la izquierda, lo que significa que las operaciones se ejecutan de izquierda a derecha. La prioridad y la asociatividad pueden controlarse mediante expresiones entre paréntesis.

2.3.5.9. Las conversiones de tipo

Existen varias funciones predefinidas que permiten pasar de un tipo de datos a otro. La lista es la siguiente:

CBool,CByte,CChar,CDate,CDbl,CDec,CInt,CLng,CObj,CShort,CSng,CStr

Estas funciones aceptan como argumento una expresión numérica o una cadena de caracteres. El tipo del resultado se indica en la siguiente tabla:

función
Resultado
Rango de valores del parámetro de la función
CBool
Booleano
Cualquier cadena o expresión numérica válida.
CByte
Byte
De 0 a 255; las fracciones se redondean.
CChar
Caracter
Cualquier expresión String válida; el valor puede estar comprendido entre 0 y 65 535.
CDate
Fecha
Cualquier representación válida de la fecha y la hora.
CDbl
Double
-1,79769313486231E+308 a
-4,94065645841247E-324 para valores negativos; 4,94065645841247E-324 a 1,79769313486231E+308 para valores positivos.
CDec
Decimal
+/-79 228 162 514 264 337 593 543 950 335 para los números sin decimales. El rango de valores de los números de 28 decimales es
+/-7,9228162514264337593543950335. El número más pequeño distinto de cero es 0,0000000000000000000000000001.
CInt
Entero
-2 147 483 648 a 2 147 483 647; las fracciones se redondean.
CLng
Long
-9 223 372 036 854 775 808 a 9 223 372 036 854 775 807; las fracciones se redondean.

CObj
Objeto
Cualquier expresión válida.
CShort
Short
-32 768 a 32 767; las fracciones se redondean.
CSng
Single
-3,402823E+38 a -1,401298E-45 para los valores negativos; 1,401298E-45 a 3,402823E+38 para los valores positivos.
CStr
Cadena
Los valores devueltos por la función Cstr dependen del argumento expresión.

A continuación se muestra un programa de ejemplo:


Module conversion
    Sub main()
        Dim var1 As Boolean = CBool("true")
        Dim var2 As Byte = CByte("100")
        Dim var3 As Char = CChar("A")
        Dim var4 As Date = CDate("30 janvier 2004")
        Dim var5 As Double = CDbl("100,45")
        Dim var6 As Decimal = CDec("1000,67")
        Dim var7 As Integer = CInt("-30")
        Dim var8 As Long = CLng("456")
        Dim var9 As Short = CShort("-14")
        Dim var10 As Single = CSng("56,78")
        Console.Out.WriteLine("var1=" & var1)
        Console.Out.WriteLine("var2=" & var2)
        Console.Out.WriteLine("var3=" & var3)
        Console.Out.WriteLine("var4=" & var4)
        Console.Out.WriteLine("var5=" & var5)
        Console.Out.WriteLine("var6=" & var6)
        Console.Out.WriteLine("var7=" & var7)
        Console.Out.WriteLine("var8=" & var8)
        Console.Out.WriteLine("var9=" & var9)
        Console.Out.WriteLine("var10=" & var10)
    End Sub
End Module

y los resultados de su ejecución:

var1=True
var2=100
var3=A
var4=30/01/2004
var5=100,45
var6=1000,67
var7=-30
var8=456
var9=-14
var10=56,78

También se puede utilizar la función CType(expression, type), tal y como se muestra en el siguiente programa:


Module ctype1
    Sub main()
        Dim var1 As Boolean = CType("true", Boolean)
        Dim var2 As Byte = CType("100", Byte)
        Dim var3 As Char = CType("A", Char)
        Dim var4 As Date = CType("30 janvier 2004", Date)
        Dim var5 As Double = CType("100,45", Double)
        Dim var6 As Decimal = CType("1000,67", Decimal)
        Dim var7 As Integer = CType("-30", Integer)
        Dim var8 As Long = CType("456", Long)
        Dim var9 As Short = CType("-14", Short)
        Dim var10 As Single = CType("56,78", Single)
        Dim var11 As String = CType("47,89", String)
        Dim var12 As String = 47.89.ToString
        Dim var13 As String = "" & 47.89
        Console.Out.WriteLine("var1=" & var1)
        Console.Out.WriteLine("var2=" & var2)
        Console.Out.WriteLine("var3=" & var3)
        Console.Out.WriteLine("var4=" & var4)
        Console.Out.WriteLine("var5=" & var5)
        Console.Out.WriteLine("var6=" & var6)
        Console.Out.WriteLine("var7=" & var7)
        Console.Out.WriteLine("var8=" & var8)
        Console.Out.WriteLine("var9=" & var9)
        Console.Out.WriteLine("var10=" & var10)
        Console.Out.WriteLine("var11=" & var11)
        Console.Out.WriteLine("var12=" & var12)
        Console.Out.WriteLine("var13=" & var13)
    End Sub
End Module

que da los siguientes resultados:

var1=True
var2=100
var3=A
var4=30/01/2004
var5=100,45
var6=1000,67
var7=-30
var8=456
var9=-14
var10=56,78
var11=47,89
var12=47,89
var13=47,89

2.4. Instrucciones de control del desarrollo del programa

2.4.1. Detener

El método Exit definido en la clase Environment permite detener la ejecución de un programa:


[Visual Basic]
Public Shared Sub Exit(ByVal exitCode As Integer )

detiene el proceso en curso y devuelve el valor exitCode al proceso padre. Este puede utilizar el valor de exitCode. En DOS, esta variable de estado se devuelve a DOS en la variable de sistema ERRORLEVEL, cuyo valor se puede comprobar en un archivo por lotes. En Unix, es la variable $? la que recupera el valor de exitCode.

    Environment.Exit(0)

detendrá la ejecución del programa con un valor de estado de 0.

2.4.2. Estructura de selección simple

if condition then
    actions_alors
else
    actions_sinon
end if
  • cada acción está en una línea
  • la cláusula else puede estar ausente.

Se pueden anidar las estructuras de selección, tal y como se muestra en el siguiente ejemplo:


' opciones
Option Explicit On 
Option Strict On

' espacios de nombres
Imports System

Module if1
    Sub main()
        Dim i As Integer = 10
        If i > 4 Then
            Console.Out.WriteLine(i & " est > " & 4)
        Else
            If i = 4 Then
                Console.Out.WriteLine(i & " est = " & 4)
            Else
                Console.Out.WriteLine(i & " est < " & 4)
            End If
        End If
    End Sub
End Module

El resultado obtenido:

10 est > 4

2.4.3. Estructura de casos

La sintaxis es la siguiente:

select case expression
    case liste_valeurs1
        actions1
case liste_valeurs2
        actions2
...
case else
        actions_sinon
end select
  • El tipo de [expression] debe ser uno de los siguientes:
Boolean, Byte, Char, Date, Decimal, Double, Integer, Long, Object, Short, Single et String
  • La cláusula [case else] puede estar ausente.
  • [liste_valeursi] son valores posibles de la expresión. [listes_valeursi] representa una lista de condiciones condición1, condición2, ..., condiciónx. Si [expression] cumple alguna de las condiciones, se ejecutan las acciones detrás de la cláusula [liste_valeursi]. Las condiciones pueden tener la siguiente forma:
  • val1 to val2: verdadero si [expression] pertenece al dominio [val1,val2]
  • val1: verdadero si [expression] es igual a val1
  • is > val1: verdadero si [expression] > val1. La palabra clave [is] puede omitirse
  • lo mismo ocurre con los operadores =, <, <=, >, >=, <>
  • solo se ejecutan las acciones relacionadas con la primera condición verificada.

Consideremos el siguiente programa:


' opciones
Option Explicit On 
Option Strict On

' espacios de nombres
Imports System

Module selectcase1
    Sub main()
        Dim i As Integer = 10
        Select Case i
            Case 1 To 4, 7 To 8
                Console.Out.WriteLine("i est dans l'intervalle [1,4] ou [7,8]")
            Case Is > 12
                Console.Out.WriteLine("i est > 12")
            Case Is < 15
                Console.Out.WriteLine("i est < 15")
            Case Is < 20
                Console.Out.WriteLine("i est < 20")
        End Select
    End Sub
End Module

Da los siguientes resultados:

i est < 15

2.4.4. Estructura de repetición

2.4.4.1. Número de repeticiones conocido


For counter [ As datatype ] = start To end [ Step step ]
   actions
Next [ counter ]

Las acciones se realizan para cada uno de los valores que toma la variable [counter]. Consideremos el siguiente programa:


' opciones
Option Explicit On 
Option Strict On

' espacios de nombres
Imports System

Module for1
    Sub main()
        Dim somme As Integer = 0
        Dim résultat As String = "somme("
        For i As Integer = 0 To 10 Step 2
            somme += i
            résultat += " " + i.ToString
        Next
        résultat += ")=" + somme.ToString
        Console.Out.WriteLine(résultat)
    End Sub
End Module

Los resultados:

somme( 0 2 4 6 8 10)=30

Otra estructura de iteración con un número conocido de iteraciones es la siguiente:


For Each element [ As datatype ] In groupe
   [ actions ]
Next [ element ]
  • groupe es una colección de objetos. La colección de objetos que ya conocemos es la matriz
  • datatype es el tipo de los objetos de la colección. En el caso de una matriz, sería el tipo de los elementos de la matriz
  • element es una variable local del bucle que tomará sucesivamente como valor todos los valores de la colección.

Así, el siguiente código:


' opciones
Option Explicit On 
Option Strict On

' espacios de nombres
Imports System

Module foreach1
    Sub main()
        Dim amis() As String = {"paul", "hélène", "jacques", "sylvie"}
        For Each nom As String In amis
            Console.Out.WriteLine(nom)
        Next
    End Sub
End Module

mostraría:

paul
hélène
jacques
sylvie

2.4.4.2. Número de repeticiones desconocido

Existen numerosas estructuras en VB.NET para este caso.


Do { While | Until } condition
   [ statements ]
Loop

El bucle se repite mientras se cumpla la condición (while) o hasta que se cumpla la condición (until). Es posible que el bucle nunca se ejecute.


Do
   [ statements ]
Loop { While | Until } condition

El bucle se repite mientras se cumpla la condición (while) o hasta que se cumpla la condición (until). El bucle siempre se ejecuta al menos una vez.


While condition
   [ statements ]
End While

El bucle se repite mientras se cumpla la condición. Es posible que el bucle nunca se ejecute. Los siguientes bucles calculan la suma de los 10 primeros números enteros.


' opciones
Option Explicit On 
Option Strict On

' espacios de nombres
Imports System

Module boucles1
    Sub main()
        Dim i, somme As Integer
        i = 0 : somme = 0
        Do While i < 11
            somme += i
            i += 1
        Loop
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do Until i = 11
            somme += i
            i += 1
        Loop
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do
            somme += i
            i += 1
        Loop Until i = 11
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do
            somme += i
            i += 1
        Loop While i < 11
        Console.Out.WriteLine("somme=" + somme.ToString)
    End Sub
End Module
somme=55
somme=55
somme=55
somme=55

2.4.4.3. Instrucciones de gestión de bucles

exit do
salir de un bucle do ... loop
exit for
salir de un bucle for

2.5. La estructura de un programa VB.NET

Un programa VB.NET que no utilice clases definidas por el usuario ni funciones distintas de la función principal Main puede tener la siguiente estructura:


' opciones
Option Explicit On 
Option Strict On

' espacios de nombres
Imports espace1
Imports ....

Module nomDuModule
    Sub main()
....
    End Sub
End Module
  • La directiva [Option Explicit on] obliga a declarar las variables. En VB.NET, esto no es obligatorio. Una variable no declarada es entonces de tipo Object.
  • La directiva [Option Strict on] prohíbe cualquier conversión de tipos de datos que pueda provocar una pérdida de datos, así como cualquier conversión entre tipos numéricos y cadenas. Por lo tanto, es necesario utilizar explícitamente funciones de conversión.
  • El programa importa todos los espacios de nombres que necesita. Aún no hemos introducido este concepto. En los programas anteriores, a menudo nos hemos encontrado con instrucciones del tipo:
        Console.Out.WriteLine(unechaine)

En realidad, deberíamos haber escrito:

        System.Console.Out.WriteLine(unechaine)

donde System es el espacio de nombres que contiene la clase [Console]. Al importar el espacio de nombres [System] con una instrucción Imports, VB.NET lo explorará sistemáticamente cuando encuentre una clase que no conozca. Repetirá la búsqueda con todos los espacios de nombres declarados hasta encontrar la clase buscada. Entonces se escribe:


' espacios de nombres
Imports System
....

        Console.Out.WriteLine(unechaine)

Un ejemplo de programa podría ser el siguiente:


' opciones
Option Explicit On 
Option Strict On

'espacios de nombres
Imports System

' módulo principal
Module main1
    Sub main()
        Console.Out.WriteLine("main1")
    End Sub
End Module

El mismo programa se puede escribir de la siguiente manera:


' opciones
Option Explicit On 
Option Strict On

'espacios de nombres
Imports System

' clase de prueba
Public Class main2
    Public Shared Sub main()
        Console.Out.WriteLine("main2")
    End Sub
End Class

Aquí utilizamos el concepto de clase que se introducirá en el siguiente capítulo. Cuando una clase de este tipo contiene un procedimiento estático (compartido) llamado main, este se ejecuta. Si introducimos esta notación aquí es porque el lenguaje gemelo de VB.NET, que es C#, solo conoce el concepto de clase, c.a.d, según el cual todo código ejecutado pertenece necesariamente a una clase. El concepto de clase pertenece a la programación orientada a objetos. Imponerlo en el diseño de cualquier programa resulta un poco torpe. Lo vemos aquí en la versión 2 del programa anterior, donde nos vemos obligados a introducir un concepto de clase y de método estático donde no es necesario. Por lo tanto, en lo sucesivo, solo introduciremos el concepto de clase cuando sea necesario. En los demás casos, utilizaremos el concepto de módulo, como en la versión 1 anterior.

2.6. Compilación y ejecución de un programa VB.NET

La compilación de un programa VB.NET solo requiere el SDK.NET. Tomemos el siguiente programa:


' opciones
Option Explicit On 
Option Strict On

' espacios de nombres
Imports System

Module boucles1
    Sub main()
        Dim i, somme As Integer
        i = 0 : somme = 0
        Do While i < 11
            somme += i
            i += 1
        Loop
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do Until i = 11
            somme += i
            i += 1
        Loop
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do
            somme += i
            i += 1
        Loop Until i = 11
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do
            somme += i
            i += 1
        Loop While i < 11
        Console.Out.WriteLine("somme=" + somme.ToString)
    End Sub
End Module

Supongamos que se encuentra en un archivo llamado [boucles1.vb]. Para compilarlo, procedemos de la siguiente manera:

dos>dir boucles1.vb
11/03/2004  15:55                  583 boucles1.vb

dos>vbc boucles1.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
pour Microsoft (R) .NET Framework version 1.1.4322.573
Copyright (C) Microsoft Corporation 1987-2002. Tous droits réservés.

dos>dir boucles1.*
11/03/2004  16:04                  601 boucles1.vb
11/03/2004  16:04                3 584 boucles1.exe

El programa vbc.exe es el compilador VB.NET. Aquí estaba en el PATH del DOS:


dos>path
PATH=E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE;E:\Program Files\Microsoft Visual Studio .NET 2003\VC7\BIN;E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools;E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\bin\prerelease;E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\bin;E:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin;E:\WINNT\Microsoft.NET\Framework\v1.1.4322;e:\winnt\system32;e:\winnt;

dos>dir E:\WINNT\Microsoft.NET\Framework\v1.1.4322\vbc.exe
21/02/2003  10:20              737 280 vbc.exe

El compilador [vbc] genera un archivo .exe ejecutable por la máquina virtual .NET:

dos>boucles1
somme=55
somme=55
somme=55
somme=55

2.7. El ejemplo IMPOTS

Nos proponemos escribir un programa que permita calcular el impuesto de un contribuyente. Nos situamos en el caso simplificado de un contribuyente que solo tiene que declarar su salario:

  • se calcula el número de partes del asalariado nbParts=nbEnfants/2 +1 si no está casado, nbEnfants/2+2 si está casado, donde nbEnfants es el número de hijos que tiene.
  • si tiene al menos tres hijos, tiene media parte más
  • se calcula su renta imponible R=0,72*S, donde S es su salario anual
  • se calcula su coeficiente familiar QF = R/nbParts
  • se calcula su impuesto I. Consideremos la siguiente tabla:
12620,0
0
0
13190
0,05
631
15640
0,1
1290,5
24 740
0,15
2072,5
31 810
0,2
3309,5
39 970
0,25
4900
48 360
0,3
6898,5
55 790
0,35
9316,5
92 970
0,4
12106
127860
0,45
16754,5
151 250
0,50
231 47,5
172 040
0,55
30710
195 000
0,60
39312
0
0,65
49062

Cada línea tiene 3 campos. Para calcular el impuesto I, se busca la primera línea donde QF<=campo1. Por ejemplo, si QF=23000, se encontrará la línea

    24740        0.15        2072.5

El impuesto I es entonces igual a 0,15*R - 2072,5*nbParts. Si QF es tal que la relación QF<=campo1 nunca se cumple, entonces se utilizan los coeficientes de la última línea. En este caso:

    0                0.65        49062

lo que da como resultado el impuesto I = 0,65*R - 49062*nbParts. El programa VB.NET correspondiente es el siguiente:


' opciones
Option Explicit On 
Option Strict On

' espacios de nombres
Imports System

Module impots
    ' ------------ principal
    Sub Main()

        ' tablas de datos necesarias para el cálculo del impuesto
        Dim Limites() As Decimal = {12620D, 13190D, 15640D, 24740D, 31810D, 39970D, 48360D, 55790D, 92970D, 127860D, 151250D, 172040D, 195000D, 0D}
        Dim CoeffN() As Decimal = {0D, 631D, 1290.5D, 2072.5D, 3309.5D, 4900D, 6898.5D, 9316.5D, 12106D, 16754.5D, 23147.5D, 30710D, 39312D, 49062D}

        ' se recupera el estado civil
        Dim OK As Boolean = False
        Dim reponse As String = Nothing
        While Not OK
            Console.Out.Write("Etes-vous marié(e) (O/N) ? ")
            reponse = Console.In.ReadLine().Trim().ToLower()
            If reponse <> "o" And reponse <> "n" Then
                Console.Error.WriteLine("Réponse incorrecte. Recommencez")
            Else
                OK = True
            End If
        End While
        Dim Marie As Boolean = reponse = "o"

        ' número de hijos
        OK = False
        Dim NbEnfants As Integer = 0
        While Not OK
            Console.Out.Write("Nombre d'enfants : ")
            reponse = Console.In.ReadLine()
            Try
                NbEnfants = Integer.Parse(reponse)
                If NbEnfants >= 0 Then
                    OK = True
                Else
                    Console.Error.WriteLine("Réponse incorrecte. Recommencez")
                End If
            Catch
                Console.Error.WriteLine("Réponse incorrecte. Recommencez")
            End Try
        End While
        ' salario
        OK = False
        Dim Salaire As Integer = 0
        While Not OK
            Console.Out.Write("Salaire annuel : ")
            reponse = Console.In.ReadLine()
            Try
                Salaire = Integer.Parse(reponse)
                If Salaire >= 0 Then
                    OK = True
                Else
                    Console.Error.WriteLine("Réponse incorrecte. Recommencez")
                End If
            Catch
                Console.Error.WriteLine("Réponse incorrecte. Recommencez")
            End Try
        End While
        ' cálculo del número de participaciones
        Dim NbParts As Decimal
        If Marie Then
            NbParts = CDec(NbEnfants) / 2 + 2
        Else
            NbParts = CDec(NbEnfants) / 2 + 1
        End If
        If NbEnfants >= 3 Then
            NbParts += 0.5D
        End If
        ' ingresos imponibles
        Dim Revenu As Decimal
        Revenu = 0.72D * Salaire

        ' coeficiente familiar
        Dim QF As Decimal
        QF = Revenu / NbParts

        ' búsqueda del tramo impositivo correspondiente a QF
        Dim i As Integer
        Dim NbTranches As Integer = Limites.Length
        Limites((NbTranches - 1)) = QF
        i = 0
        While QF > Limites(i)
            i += 1
        End While
        ' el impuesto
        Dim impots As Integer = CInt(i * 0.05D * Revenu - CoeffN(i) * NbParts)

        ' se muestra el resultado
        Console.Out.WriteLine(("Impôt à payer : " & impots))
    End Sub
End Module

El programa se compila en una ventana de DOS mediante:

dos>vbc impots1.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573

dos>dir impots1.exe
24/02/2004  15:42                5 632 impots1.exe

La compilación genera un ejecutable llamado impots.exe. Cabe señalar que impots.exe no es directamente ejecutable por el procesador. En realidad, contiene código intermedio que solo es ejecutable en una plataforma .NET. Los resultados obtenidos son los siguientes:

dos>impots1
Etes-vous marié(e) (O/N) ? o
Nombre d'enfants : 3
Salaire annuel : 200000
Impôt à payer : 16400
dos>impots1
Etes-vous marié(e) (O/N) ? n
Nombre d'enfants : 2
Salaire annuel : 200000
Impôt à payer : 33388
dos>impots1
Etes-vous marié(e) (O/N) ? w
Réponse incorrecte. Recommencez
Etes-vous marié(e) (O/N) ? q
Réponse incorrecte. Recommencez
Etes-vous marié(e) (O/N) ? o
Nombre d'enfants : q
Réponse incorrecte. Recommencez
Nombre d'enfants : 2
Salaire annuel : q
Réponse incorrecte. Recommencez
Salaire annuel : 1
Impôt à payer : 0

2.8. Argumentos del programa principal

El procedimiento principal Main puede admitir como parámetro una matriz de cadenas:


    Sub main(ByVal args() As String)

El parámetro args es una matriz de cadenas de caracteres que recibe los argumentos pasados en la línea de comandos al llamar al programa.

  • args.Length es el número de elementos de la matriz args
  • args(i) es el elemento i de la matriz

Si se ejecuta el programa P con el comando: P arg0 arg1 … argn y si el procedimiento Main del programa P se declara de la siguiente manera:


    Sub main(ByVal args() As String)

tendremos arg(0)="arg0", arg(1)="arg1" … He aquí un ejemplo:


' instrucciones
Option Strict On
Option Explicit On 

' espacios de nombres
Imports System

Module arg
    Sub main(ByVal args() As String)
        ' número de argumentos
        console.out.writeline("Il y a " & args.length & " arguments")
        Dim i As Integer
        For i = 0 To args.Length - 1
            Console.Out.WriteLine("argument n° " & i & "=" & args(i))
        Next
    End Sub
End Module

La ejecución da los siguientes resultados:

dos>arg1 a b c
Il y a 3 arguments
argument n° 0=a
argument n° 1=b
argument n° 2=c

2.9. Las enumeraciones

Una enumeración es un tipo de datos cuyo dominio de valores es un conjunto de constantes enteras. Consideremos un programa que tiene que gestionar las calificaciones de un examen. Habría cinco: Aceptable, AssezBien, Bien, TrèsBien, Excelente. Entonces, podríamos definir una enumeración para estas cinco constantes:


    Enum mention
        Passable
        AssezBien
        Bien
        TrésBien
        Excellent
    End Enum

Internamente, estas cinco constantes se codifican mediante números enteros consecutivos que comienzan por 0 para la primera constante, 1 para la siguiente, etc. Se puede declarar una variable para que adopte estos valores en la enumeración:


        ' una variable que toma sus valores de la enumeración mencionada
        Dim maMention As mention = mention.Passable

Se puede comparar una variable con los diferentes valores posibles de la enumeración:


        ' comprobación con valor de la enumeración
        If (maMention = mention.Passable) Then
            Console.Out.WriteLine("Peut mieux faire")
        End If

Se pueden obtener todos los valores de la enumeración:


        For Each m In mention.GetValues(maMention.GetType)
            Console.Out.WriteLine(m)
        Next

Del mismo modo que el tipo simple Integer es equivalente a la estructura Int32, el tipo simple Enum es equivalente a la estructura Enum. Esta clase tiene un método estático GetValues que permite obtener todos los valores de un tipo enumerado que se pasa como parámetro. Este debe ser un objeto de tipo Type, que es una clase de información sobre el tipo de un dato. El tipo de una variable v se obtiene mediante v.GetType(). Por lo tanto, aquí maMention.GetType() devuelve el objeto Type de la enumeración mentions y Enum.GetValues(maMention.GetType()) la lista de valores de la enumeración mentions.

Esto es lo que muestra el siguiente programa:


' directivas
Option Strict On
Option Explicit On 

' espacios de nombres
Imports System

Public Module enum2

    ' una enumeración
    Enum mention
        Passable
        AssezBien
        Bien
        TrèsBien
        Excellent
    End Enum

    ' página de prueba
    Sub Main()

        ' una variable que toma sus valores de la enumeración mencionada
        Dim maMention As mention = mention.Passable

        ' visualización del valor de la variable
        Console.Out.WriteLine("mention=" & maMention)

        ' prueba con el valor de la enumeración
        If (maMention = mention.Passable) Then
            Console.Out.WriteLine("Peut mieux faire")
        End If

        ' lista de menciones literales
        For Each m As mention In [Enum].GetValues(maMention.GetType)
            Console.Out.WriteLine(m.ToString)
        Next

        ' lista de menciones completas
        For Each m As Integer In [Enum].GetValues(maMention.GetType)
            Console.Out.WriteLine(m)
        Next
    End Sub
End Module

Los resultados de la ejecución son los siguientes:


dos>enum2
mention=0
Peut mieux faire
Passable
AssezBien
Bien
TrèsBien
Excellent
0
1
2
3
4

2.10. Gestión de excepciones

Muchas funciones VB.NET pueden generar excepciones, es decir, errores. Cuando una función puede generar una excepción, el programador debe gestionarla con el fin de obtener programas más resistentes a los errores: siempre hay que evitar que una aplicación se «cuelgue» de forma imprevista.

La gestión de una excepción se realiza según el siguiente esquema:

try
    appel de la fonction susceptible de générer l'exception
catch  e as Exception e)
    traiter l'exception e
end try
instruction suivante

Si la función no genera una excepción, se pasa a la siguiente instrucción; de lo contrario, se pasa al cuerpo de la cláusula catch y luego a la siguiente instrucción. Cabe destacar los siguientes puntos:

  • e es un objeto derivado del tipo Exception. Se puede ser más preciso utilizando tipos como IOException, SystemException, etc.: existen varios tipos de excepciones. Al escribir catch e as Exception, se indica que se desea gestionar todos los tipos de excepciones. Si el código de la cláusula try puede generar varios tipos de excepciones, es posible que se desee ser más preciso gestionando la excepción con varias cláusulas catch:
try
    appel de la fonction susceptible de générer l'exception
catch e as IOException 
    traiter l'exception e
catch  e as SystemException
    traiter l'exception e
end try
instruction suivante
  • Se puede añadir a las cláusulas try/catch una cláusula finally:
try
    appel de la fonction susceptible de générer l'exception
catch  e as Exception
    traiter l'exception e
finally
    code exécuté après try ou catch
end try
instruction suivante

Independientemente de si hay una excepción o no, el código de la cláusula finally siempre se ejecutará.

  • En la cláusula catch, es posible que no se desee utilizar el objeto Exception disponible. En lugar de escribir catch e as Exception, se escribe entonces catch.
  • La clase Exception tiene una propiedad «Message» que contiene un mensaje con los detalles del error que se ha producido. Por lo tanto, si queremos mostrarlo, escribiremos:
catch e as Exception
    Console.Error.WriteLine("L'erreur suivante s'est produite : "+e.Message);
    ...
end try
  • La clase Exception tiene un método ToString que devuelve una cadena de caracteres que indica el tipo de la excepción, así como el valor de la propiedad Message. Así, se puede escribir:
catch  ex as Exception
    Console.Error.WriteLine("L'erreur suivante s'est produite : "+ex.ToString)
    ...
end try

El siguiente ejemplo muestra una excepción generada por el uso de un elemento de matriz inexistente:


' opciones
Option Explicit On 
Option Strict On

' espacios de nombres
Imports System

Module tab1
    Sub Main()
        ' declaración e inicialización de una matriz
        Dim tab() As Integer = {0, 1, 2, 3}
        Dim i As Integer

        ' visualización de una matriz con un for
        For i = 0 To tab.Length - 1
            Console.Out.WriteLine(("tab[" & i & "]=" & tab(i)))
        Next i

        ' Visualización de una matriz con un bucle «for each»
        Dim élmt As Integer
        For Each élmt In tab
            Console.Out.WriteLine(élmt)
        Next élmt

        ' generación de una excepción
        Try
            tab(100) = 6
        Catch e As Exception
            Console.Error.WriteLine(("L'erreur suivante s'est produite : " & e.Message))
        End Try
    End Sub
End Module

La ejecución del programa da los siguientes resultados:

dos>exception1
tab[0]=0
tab[1]=1
tab[2]=2
tab[3]=3
0
1
2
3
L'erreur suivante s'est produite : L'index se trouve en dehors des limites du tableau.

Aquí hay otro ejemplo en el que se gestiona la excepción provocada por la asignación de una cadena de caracteres a un número cuando la cadena no representa un número:


' opciones
Option Strict On
Option Explicit On 

'importaciones
Imports System

Public Module console1
  Public Sub Main()
    ' Se solicita el nombre
    System.Console.Write("Nom : ")

        ' lectura de la respuesta
    Dim nom As String = System.Console.ReadLine()

        ' se solicita la edad
    Dim age As Integer
    Dim ageOK As Boolean = False
    Do While Not ageOK
      ' pregunta
      Console.Out.Write("âge : ")
      ' lectura y verificación de la respuesta
      Try
        age = Int32.Parse(System.Console.ReadLine())
        If age < 0 Then Throw New Exception
        ageOK = True
      Catch
        Console.Error.WriteLine("Age incorrect, recommencez...")
      End Try
    Loop

        ' visualización final
    Console.Out.WriteLine("Vous vous appelez [" & nom & "] et vous avez [" & age & "] ans")
  End Sub
End Module

Algunos resultados de la ejecución:

dos>console1
Nom : dupont
âge : 23
Vous vous appelez dupont et vous avez 23 ans
dos>console1
Nom : dupont
âge : xx
Age incorrect, recommencez...
âge : 12
Vous vous appelez dupont et vous avez 12 ans

2.11. Pasar parámetros a una función

Aquí nos centramos en cómo se pasan los parámetros a una función. Consideremos la función:


    Sub changeInt(ByVal a As Integer)
        a = 30
        Console.Out.WriteLine(("Paramètre formel a=" & a))
    End Sub    

En la definición de la función, a se denomina parámetro formal. Solo está ahí para la definición de la función changeInt. También podría haberse llamado b. Veamos ahora un ejemplo de uso de esta función:


    Sub Main()
        Dim age As Integer = 20
        changeInt(age)
        Console.Out.WriteLine(("Paramètre effectif age=" & age))
    End Sub

Aquí, en la instrucción changeInt(edad), age es el parámetro efectivo que transmitirá su valor al parámetro formal a. Nos interesa saber cómo un parámetro formal recupera el valor del parámetro efectivo que le corresponde.

2.11.1. Pasaje por valor

El siguiente ejemplo nos muestra que los parámetros de una función o procedimiento se pasan por defecto por valor: es decir, el valor del parámetro efectivo se copia en el parámetro formal correspondiente. Tenemos dos entidades distintas. Si la función modifica el parámetro formal, el parámetro efectivo no se ve modificado en absoluto.


' opciones
Option Explicit On 
Option Strict On

' paso de parámetros por valor a una función
Imports System

Module param1
    Sub Main()
        Dim age As Integer = 20
        changeInt(age)
        Console.Out.WriteLine(("Paramètre effectif age=" & age))
    End Sub

    Sub changeInt(ByVal a As Integer)
        a = 30
        Console.Out.WriteLine(("Paramètre formel a=" & a))
    End Sub
End Module

Los resultados obtenidos son los siguientes:

Paramètre formel a=30
Paramètre effectif age=20

El valor 20 del parámetro efectivo se ha copiado en el parámetro formal a. Este se ha modificado posteriormente. El parámetro efectivo, por su parte, no ha sufrido cambios. Este modo de paso es adecuado para los parámetros de entrada de una función.

2.11.2. Pase por referencia

En un paso por referencia, el parámetro efectivo y el parámetro formal son una misma entidad. Si la función modifica el parámetro formal, el parámetro efectivo también se modifica. En VB.NET, el parámetro formal debe ir precedido de la palabra clave ByRef. A continuación se muestra un ejemplo:


' opciones
Option Explicit On 
Option Strict On

' paso de parámetros por valor a una función
Imports System

Module param2
    Sub Main()
        Dim age As Integer = 20
        changeInt(age)
        Console.Out.WriteLine(("Paramètre effectif age=" & age))
    End Sub

    Sub changeInt(ByRef a As Integer)
        a = 30
        Console.Out.WriteLine(("Paramètre formel a=" & a))
    End Sub
End Module

y los resultados de la ejecución:

Paramètre formel a=30
Paramètre effectif age=30

El parámetro efectivo ha seguido la modificación del parámetro formal. Este modo de paso es adecuado para los parámetros de salida de una función.