Etiqueta: truco

  • Error al guardar datos decimales – El código para C#

    Aquí tienes el código para C# de la aplicación de ejemplo del artículo Error al guardar datos decimales: El valor del parámetro ‘xxx’ está fuera del intervalo.

    Nota:
    Si buscabas el código para Visual Basic está en este otro enlace:
    Error al guardar datos decimales – El código para Visual Basic.

    Cuando lo tenga publicado, te pondré el enlace para descargar la solución de Visual Studio 2017 tanto para VB como para C#.

    El código de C#

    //-----------------------------------------------------------------------------
    //  Ejemplo para el error de asignar a decimal(4,4)                 (07/Dic/18)
    //
    // (c) Guillermo (elGuille) Som, 2018
    //-----------------------------------------------------------------------------
    
    using System;
    using System.Data.SqlClient;
    using System.Text;
    using System.Windows.Forms;
    
    namespace SQL_Error_decimal_cs
    {
        public partial class Form1 : Form
        {
    
    
            //--------------------------------------------------------------------------
            // Los campos para acceder a la base de datos
            //--------------------------------------------------------------------------
    
            /// <summary>
            /// El usuario para acceder a la base de datos de SQL Server.<br />
            /// Si es una cadena vacía se usará la seguridad integrada de Windows.
            /// </summary>
            private string userDb = "UsuarioErrDec";
    
            /// <summary>
            /// El password del usuario que accede a la base de datos de SQL Server
            /// </summary>
            private string passwordDB = "123456";
    
            /// <summary>
            /// El servidor donde está la base de datos.<br />
            /// Normalmente será .\SQLEXPRESS o (local)
            /// </summary>
            private string serverName = @".\SQLEXPRESS";
            /// <summary>
            /// El nombre de la base de datos de SQL Server
            /// </summary>
            private string databaseName = "ErrorDecimal";
    
            /// <summary>
            /// Devuelve la cadena de conexión a la base de datos de SQL Server<br />
            /// Si el usuario es una cadena vacía, se usará la seguridad integrada de Windows
            /// </summary>
            private string ConnectionString {
                get {
                    var sb = new SqlConnectionStringBuilder();
                    sb.DataSource = serverName;
                    sb.InitialCatalog = databaseName;
                    if (String.IsNullOrWhiteSpace(userDb))
                    {
                        sb.IntegratedSecurity = true;
                    } else
                    {
                        sb.UserID = userDb;
                        sb.Password = passwordDB;
                    }
                    return sb.ConnectionString;
                }
            }
    
    
    
            //--------------------------------------------------------------------------
            // Añadir un valor a las tablas
            //--------------------------------------------------------------------------
            private (bool hayError, string msg) AñadirMiTabla1(decimal valor)
            {
                var sel = "INSERT INTO MiTabla1 (Decimal_4_4) " +
                          "VALUES (@Decimal_4_4)";
    
                var retVal = (hayError: false, msg: "");
    
                var sCon = ConnectionString;
    
                using (SqlConnection con = new SqlConnection(sCon))
                {
                    var cmd = new SqlCommand(sel, con);
                    cmd.Parameters.AddWithValue("@Decimal_4_4", valor);
    
                    con.Open();
    
                    try
                    {
                        var ret = Convert.ToInt32(cmd.ExecuteNonQuery());
    
                        retVal.hayError = (ret < 1);
                        retVal.msg = "Todo OK. cmd.ExecuteNonQuery() = " + ret.ToString();
                    }
                    catch (Exception ex)
                    {
                        retVal.msg = ex.Message;
                        retVal.hayError = true;
                    }
                    con.Close();
                }
                return retVal;
            }
    
            private (bool hayError, string msg) AñadirMiTabla2(decimal[] valores)
            {
                var sel = "INSERT INTO MiTabla2 (Decimal_6_4, Decimal_18_6) " +
                          "VALUES (@Decimal_6_4, @Decimal_18_6)";
    
                var retVal = (hayError:false, msg:"");
                
                var sCon = ConnectionString;
    
                using (SqlConnection con = new SqlConnection(sCon))
                {
                    SqlCommand cmd = new SqlCommand(sel, con);
                    cmd.Parameters.AddWithValue("@Decimal_6_4", valores[0]);
                    cmd.Parameters.AddWithValue("@Decimal_18_6", valores[1]);
    
                    con.Open();
    
                    try
                    {
                        var ret = Convert.ToInt32(cmd.ExecuteNonQuery());
    
                        retVal.hayError = (ret < 1);
                        retVal.msg = "Todo OK. cmd.ExecuteNonQuery() = " + ret.ToString();
                    }
                    catch (Exception ex)
                    {
                        retVal.msg = ex.Message;
                        retVal.hayError = true;
                    }
                    con.Close();
                }
                return retVal;
            }
    
    
    
            private string leerMiTabla(string tabla)
            {
                var sel = "SELECT * FROM " + tabla;
    
                var retVal = "";
    
                var sCon = ConnectionString;
    
                using (SqlConnection con = new SqlConnection(sCon))
                {
                    var cmd = new SqlCommand(sel, con);
    
                    con.Open();
    
                    try
                    {
                        var ret = cmd.ExecuteReader();
    
                        StringBuilder sb = new StringBuilder();
    
                        while (ret.Read())
                        {
                            sb.AppendLine(String.Format("{0} = {1}", ret.GetName(0), ret[0]));
    
                            if (ret.FieldCount > 1)
                                sb.AppendLine(String.Format("{0} = {1}", ret.GetName(1), ret[1]));
                        };
                        retVal = sb.ToString();
                    }
                    catch (Exception ex)
                    {
                        retVal = "ERROR: " + ex.Message;
                    }
                    con.Close();
                };
                return retVal;
            }
    
            //--------------------------------------------------------------------------
            // Para aceptar la coma como decimal en las cajas numéricas
            //--------------------------------------------------------------------------
            /// <summary>
            /// El separador de decimales para los campos numéricos
            /// </summary>
            const string SeparadorDecimal = ",";
    
            /// <summary>
            /// Para indicar qué tecla "decimal" no se debe admitir
            /// </summary>
            const string NoSeparadorDecimal = ".";
    
            /// <summary>
            /// Comprobar si se aceptan las teclas en una caja de texto.
            /// En la pulsación de los controles numéricos
            /// aceptar solo los caracteres numéricos,
            /// el valor negativo, el separador de decimales
            /// y las teclas Intro, Delete, Back (borrar hacia atrás)
            ///
            /// Es raro, si teclasAceptadas es: ",-1234567890" también acepta el punto
            /// </summary>
            private char AceptarTeclas(KeyPressEventArgs e, string teclasAceptadas)
            {
                char c = e.KeyChar;
    
                if (c == Convert.ToChar(Keys.Return))
                {
                    // con esto hacemos que se ignore la pulsación
                    e.Handled = true;
                    // se manda al siguiente control
                    SendKeys.Send("{TAB}");
                }
                else if (c == Convert.ToChar(NoSeparadorDecimal))
                {
                    e.KeyChar = Convert.ToChar(SeparadorDecimal);
                }
                else if (teclasAceptadas.Contains(c.ToString()))
                {
                    // no hacer nada, se aceptan
                }
                else if (c == Convert.ToChar(Keys.Delete) || c == Convert.ToChar(Keys.Back))
                {
                    // no hacer nada, se aceptan
                }
                else
                {
                    e.Handled = true;
                }
                return c;
            }
    
    
    
            //--------------------------------------------------------------------------
            // Los métodos de evento del formulario
            //--------------------------------------------------------------------------
    
            private void btnCerrar_Click(object sender, EventArgs e)
            {
                this.Close();
            }
    
            private void btnAsignarTabla1_Click(object sender, EventArgs e)
            {
                var d = 0M;
                Decimal.TryParse(txtTabla1_campo1.Text, out d);
                var ret = AñadirMiTabla1(d);
    
                txtMensaje1.Text = "";
                if (ret.hayError)
                    txtMensaje1.Text = "ERROR\r\n";
                txtMensaje1.Text += ret.msg;
            }
    
            private void btnAsignarTabla2_Click(object sender, EventArgs e)
            {
                var valores = new decimal[12];
                var d = 0M;
    
                Decimal.TryParse(txtTabla2_campo1.Text, out d);
                valores[0] = d;
    
                d = 0M;
                Decimal.TryParse(txtTabla2_campo2.Text, out d);
                valores[1] = d;
    
                var ret = AñadirMiTabla2(valores);
    
                txtMensaje2.Text = "";
                if (ret.hayError)
                    txtMensaje2.Text = "ERROR\r\n";
                txtMensaje2.Text += ret.msg;
            }
    
            private void btnMostrar1_Click(object sender, EventArgs e)
            {
                // mostrar los datos de MiTabla1
                txtMensaje1.Text = leerMiTabla("MiTabla1");
            }
    
            private void btnMostrar2_Click(object sender, EventArgs e)
            {
                // mostrar los datos de MiTabla2
                txtMensaje2.Text = leerMiTabla("MiTabla2");
            }
    
            private void txt_KeyPress(object sender, KeyPressEventArgs e)
            {
                AceptarTeclas(e, SeparadorDecimal + "-1234567890");
            }
    
            public Form1()
            {
                InitializeComponent();
            }
    
    <
    
            private void Form1_KeyDown(object sender, KeyEventArgs e)
            {
                // detecta la pulsación de las teclas en el formulario
                // antes de mandarla a los controles
                // En el diseñador de formularios tienes que
                // asignar un valor True a la propiedad KeyPreview
    
                if (e.Modifiers == Keys.Control)
                {
    
    
                    if (e.KeyCode == Keys.C)
                    {
                        // copiar el texto
                        if (ActiveControl is TextBox)
                        {
                            //Dim texto = ActiveControl.Text
                            //Clipboard.SetText(texto)
                            var txt = ActiveControl as TextBox;
                            if (txt == null) return;
                            txt.Copy();
    
                            e.Handled = true;
                        }
                    }
                    else if (e.KeyCode == Keys.V)
                    {
                        // pegar el texto
                        if (ActiveControl is TextBox)
                        {
                            var txt = ActiveControl as TextBox;
                            if (txt == null) return;
                            txt.Paste();
    
                            e.Handled = true;
                        }
                    }
                    else if (e.KeyCode == Keys.X)
                    {
                        // cortar el texto
                        if (ActiveControl is TextBox)
                        {
                            var txt = ActiveControl as TextBox;
                            if (txt == null) return;
                            txt.Cut();
    
                            e.Handled = true;
                        }
                    }
                    else if (e.KeyCode == Keys.Z)
                    {
                        //deshacer
                        if (ActiveControl is TextBox)
                        {
                            var txt = ActiveControl as TextBox;
                            if (txt == null) return;
                            if (txt.CanUndo)
                            {
                                txt.Undo();
                            }
                            e.Handled = true;
                        }
                    }
                }
            }
        }
    }
    

    Espero que te sea de utilidad.

    Nos vemos
    Guillermo

  • Error al guardar datos decimales – El código para Visual Basic

    Aquí tienes el código para Visual Basic de la aplicación de ejemplo del artículo Error al guardar datos decimales: El valor del parámetro ‘xxx’ está fuera del intervalo.

    Nota:
    Si buscabas el código para C# está en este otro enlace:
    Error al guardar datos decimales – El código para C#.

    Cuando lo tenga publicado, te pondré el enlace para descargar la solución de Visual Studio 2017 tanto para VB como para C#.

    El código de Visual Basic .NET

    '------------------------------------------------------------------------------
    '  Ejemplo para el error de asignar a decimal(4,4)                  (07/Dic/18)
    '
    ' (c) Guillermo (elGuille) Som, 2018
    '------------------------------------------------------------------------------
    Option Strict On
    Option Infer On
    
    Imports System
    'Imports System.Data
    Imports System.Data.SqlClient
    Imports System.Text
    
    Public Class Form1
        '--------------------------------------------------------------------------
        ' Los campos para acceder a la base de datos
        '--------------------------------------------------------------------------
    
        ''' <summary>
        ''' El usuario para acceder a la base de datos de SQL Server.<br />
        ''' Si es una cadena vacía se usará la seguridad integrada de Windows.
        ''' </summary>
        Private userDb As String = "UsuarioErrDec"
    
        ''' <summary>
        ''' El password del usuario que accede a la base de datos de SQL Server
        ''' </summary>
        Private passwordDB As String = "123456"
    
        ''' <summary>
        ''' El servidor donde está la base de datos.<br />
        ''' Normalmente será .\SQLEXPRESS o (local)
        ''' </summary>
        Private serverName As String = ".\SQLEXPRESS" ' "(local)"
        ''' <summary>
        ''' El nombre de la base de datos de SQL Server
        ''' </summary>
        Private databaseName As String = "ErrorDecimal"
    
        ''' <summary>
        ''' Devuelve la cadena de conexión a la base de datos de SQL Server<br />
        ''' Si el usuario es una cadena vacía, se usará la seguridad integrada de Windows
        ''' </summary>
        Private ReadOnly Property ConnectionString As String
            Get
                With New SqlConnectionStringBuilder
                    .DataSource = serverName
                    .InitialCatalog = databaseName
                    If String.IsNullOrWhiteSpace(userDb) Then
                        .IntegratedSecurity = True
                    Else
                        .UserID = userDb
                        .Password = passwordDB
                    End If
    
                    Return .ConnectionString
                End With
            End Get
        End Property
    
        '--------------------------------------------------------------------------
        ' Añadir un valor a las tablas
        '--------------------------------------------------------------------------
        Private Function AñadirMiTabla1(valor As Decimal) As (hayError As Boolean,
                                                             msg As String)
            Dim sel = "INSERT INTO MiTabla1 (Decimal_4_4) 
                       VALUES (@Decimal_4_4)"
    
            Dim retVal = (hayError:=False, msg:="")
    
            Dim sCon = ConnectionString
    
            Using con As New SqlConnection(sCon)
                Dim cmd As New SqlCommand(sel, con)
    
                cmd.Parameters.AddWithValue("@Decimal_4_4", valor)
    
                con.Open()
    
                Try
                    Dim ret = CInt(cmd.ExecuteNonQuery())
                    'Dim ret = CInt(cmd.ExecuteScalar())
    
                    retVal.hayError = (ret < 1)
                    retVal.msg = "Todo OK. cmd.ExecuteNonQuery() = " & ret.ToString
    
                Catch ex As Exception
                    retVal.msg = ex.Message
                    retVal.hayError = True
                End Try
    
                con.Close()
            End Using
    
            Return retVal
        End Function
    
        Private Function AñadirMiTabla2(valores() As Decimal) As (hayError As Boolean,
                                                             msg As String)
            Dim sel = "INSERT INTO MiTabla2 (Decimal_6_4, Decimal_18_6) 
                       VALUES (@Decimal_6_4, @Decimal_18_6)"
    
            Dim retVal = (hayError:=False, msg:="")
    
            Dim sCon = ConnectionString
    
            Using con As New SqlConnection(sCon)
                Dim cmd As New SqlCommand(sel, con)
    
                cmd.Parameters.AddWithValue("@Decimal_6_4", valores(0))
                cmd.Parameters.AddWithValue("@Decimal_18_6", valores(1))
    
                con.Open()
    
                Try
                    Dim ret = CInt(cmd.ExecuteNonQuery())
    
                    retVal.hayError = (ret < 1)
                    retVal.msg = "Todo OK. cmd.ExecuteNonQuery() = " & ret.ToString
    
                Catch ex As Exception
                    retVal.msg = ex.Message
                    retVal.hayError = True
                End Try
    
                con.Close()
            End Using
    
            Return retVal
        End Function
    
        Private Function leerMiTabla(tabla As String) As String
            Dim sel = "SELECT * FROM " & tabla
    
            Dim retVal = ""
    
            Dim sCon = ConnectionString
    
            Using con As New SqlConnection(sCon)
                Dim cmd As New SqlCommand(sel, con)
    
                con.Open()
    
                Try
                    Dim ret = cmd.ExecuteReader
    
                    Dim sb As New StringBuilder
    
                    While ret.Read()
                        sb.AppendLine(String.Format("{0} = {1}", ret.GetName(0), ret(0)))
    
                        If ret.FieldCount > 1 Then
                            sb.AppendLine(String.Format("{0} = {1}", ret.GetName(1), ret(1)))
                        End If
                    End While
    
                    retVal = sb.ToString
    
                Catch ex As Exception
                    retVal = "ERROR: " & ex.Message
                End Try
    
                con.Close()
            End Using
    
            Return retVal
        End Function
    
    
        '--------------------------------------------------------------------------
        ' Para aceptar la coma como decimal en las cajas numéricas
        '--------------------------------------------------------------------------
    
        ''' <summary>
        ''' El separador de decimales para los campos numéricos
        ''' </summary>
        Private Const SeparadorDecimal As String = ","
    
        ''' <summary>
        ''' Para indicar qué tecla "decimal" no se debe admitir
        ''' </summary>
        Private Const NoSeparadorDecimal As String = "."
    
        ''' <summary>
        ''' Comprobar si se aceptan las teclas en una caja de texto.
        ''' En la pulsación de los controles numéricos
        ''' aceptar solo los caracteres numéricos, 
        ''' el valor negativo, el separador de decimales
        ''' y las teclas Intro, Delete, Back (borrar hacia atrás)
        ''' 
        ''' Es raro, si teclasAceptadas es: ",-1234567890" también acepta el punto
        ''' </summary>
        Private Function AceptarTeclas(e As KeyPressEventArgs, teclasAceptadas As String) As Char
            Dim c = e.KeyChar
            If c = Convert.ToChar(Keys.Return) Then
                ' con esto hacemos que se ignore la pulsación
                e.Handled = True
                ' se manda al siguiente control
                SendKeys.Send("{TAB}")
            ElseIf c = Convert.ToChar(NoSeparadorDecimal) Then
                e.KeyChar = Convert.ToChar(SeparadorDecimal)
            ElseIf teclasAceptadas.Contains(c) Then
                ' no hacer nada, se aceptan
            ElseIf c = Convert.ToChar(Keys.Delete) OrElse
                   c = Convert.ToChar(Keys.Back) Then
                ' no hacer nada, se aceptan
            Else
                e.Handled = True
            End If
    
            Return c
        End Function
    
        '--------------------------------------------------------------------------
        ' Los métodos de evento del formulario
        '--------------------------------------------------------------------------
    
        Private Sub btnCerrar_Click(sender As Object, e As EventArgs) Handles btnCerrar.Click
            Me.Close()
        End Sub
    
        Private Sub btnAsignarTabla1_Click(sender As Object, e As EventArgs) Handles btnAsignarTabla1.Click
            Dim d = 0@
            Decimal.TryParse(txtTabla1_campo1.Text, d)
            Dim ret = AñadirMiTabla1(d)
    
            txtMensaje1.Text = ""
            If ret.hayError Then
                txtMensaje1.Text = "ERROR" & vbCrLf
            End If
            txtMensaje1.Text &= ret.msg
        End Sub
    
        Private Sub btnAsignarTabla2_Click(sender As Object, e As EventArgs) Handles btnAsignarTabla2.Click
            Dim valores(1) As Decimal
            Dim d = 0@
            Decimal.TryParse(txtTabla2_campo1.Text, d)
            valores(0) = d
            d = 0@
            Decimal.TryParse(txtTabla2_campo2.Text, d)
            valores(1) = d
    
            Dim ret = AñadirMiTabla2(valores)
    
            txtMensaje2.Text = ""
            If ret.hayError Then
                txtMensaje2.Text = "ERROR" & vbCrLf
            End If
            txtMensaje2.Text &= ret.msg
        End Sub
    
        Private Sub txt_KeyPress(sender As Object, e As KeyPressEventArgs) Handles _
                                            txtTabla2_campo1.KeyPress, txtTabla1_campo1.KeyPress,
    txtTabla2_campo2.KeyPress AceptarTeclas(e, SeparadorDecimal &
    "-1234567890") End Sub Private Sub btnMostrar1_Click(sender As Object, e As EventArgs) Handles btnMostrar1.Click ' mostrar los datos de MiTabla1 txtMensaje1.Text = leerMiTabla("MiTabla1") End Sub Private Sub btnMostrar2_Click(sender As Object, e As EventArgs) Handles btnMostrar2.Click ' mostrar los datos de MiTabla2 txtMensaje2.Text = leerMiTabla("MiTabla2") End Sub Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown ' detecta la pulsación de las teclas en el formulario ' antes de mandarla a los controles ' En el diseñador de formularios tienes que ' asignar un valor True a la propiedad KeyPreview If e.Modifiers = Keys.Control Then If e.KeyCode = Keys.C Then ' copiar el texto If TypeOf ActiveControl Is TextBox Then 'Dim texto = ActiveControl.Text 'Clipboard.SetText(texto) Dim txt = TryCast(ActiveControl, TextBox) If txt Is Nothing Then Return txt.Copy() e.Handled = True End If ElseIf e.KeyCode = Keys.V Then ' pegar el texto If TypeOf ActiveControl Is TextBox Then Dim txt = TryCast(ActiveControl, TextBox) If txt Is Nothing Then Return txt.Paste() e.Handled = True End If ElseIf e.KeyCode = Keys.X Then ' cortar el texto If TypeOf ActiveControl Is TextBox Then Dim txt = TryCast(ActiveControl, TextBox) If txt Is Nothing Then Return txt.Cut() e.Handled = True End If ElseIf e.KeyCode = Keys.Z Then 'deshacer If TypeOf ActiveControl Is TextBox Then Dim txt = TryCast(ActiveControl, TextBox) If txt Is Nothing Then Return If txt.CanUndo Then txt.Undo() End If e.Handled = True End If End If End If End Sub End Class

    Espero que te sea de utilidad.

    Nos vemos
    Guillermo

  • Cómo usar las Tuplas en Visual Basic y C Sharp con .NET Core 2.1 (o Visual Studio 2017 con .NET 4.7.2)

    Pues eso… aquí te voy a explicar (con ejemplo de código) cómo definir y usar las tuplas (Tuples) en Visual Basic .NET (y para los amantes de C#, también pondré algunos ejemplos en ese lenguaje puntoycomagudo Winking smile)

    En esta primera «entrega» te voy a dar 3 ejemplos (+ 1 extra) de cómo usar las tuplas con .NET Core 2.1 (si prefieres hacerlo con .NET normal tendrás que usar la versión 4.7.2 o superior) en una aplicación de Consola.

    El contenido es el siguiente:

    Ejemplo 1: definir las tuplas sin nombres
    Ejemplo 2: definir las tuplas con nombres y asignación después de definir
    Ejemplo 3: definir las tuplas con nombres y asignando al definir
    Ejemplo 4: definir las tuplas con nombres y asignando al definir (al estilo de C#)
    Ejemplo 5: definir un método que recibe un array tuplas

    Mmmmm… te dije 3 + un extra y resulta que son 4 + un extra Winking smile

    Si no sabes qué son las tuplas, decirte que son como una estructura (Struct) pero definidas de forma «directa» sin necesidad de crear el tipo previamente.

    Si quieres saber más sobre las tuplas, te recomiendo que leas la documentación de .NET:
    Tipos de tupla en C#
    Tuplas (Visual Basic)

    Código de uso de Tuplas (Tuples) en Visual Basic

    Ejemplo 1: Ejemplo básico de tuplas sin definir los nombres de los miembros:

    ' Al definirla de esta forma 
    ' tenemos una tupla con dos elementos del tipo cadena
    Dim t1 = ("Hola", "mundo")
    
    ' para acceder a los miembros usaremos Item1, Item2
    Console.WriteLine("{0} {1}", t1.Item1, t1.Item2)

    Ejemplo 2: Definimos una tupla con miembros con nombres, asignando los nombres individualmente. Para acceder a los miembros de la tupla usamos los nombres.

    ' definimos una tupla con miembros con nombres
    Dim t2 As (saludo As String, destino As String)
    ' para acceder a los miembros, usamos los nombres
    t2.saludo = "Hola"
    t2.destino = "Mundo"
    
    Console.WriteLine("{0} {1}", t2.saludo, t2.destino)

    Ejemplo 3: Definimos una tupla con miembros con nombres, asignando los valores al definirla. Para acceder a los miembros, usamos los nombres.

    ' definimos una tupla con miembros con nombres
    Dim t2 As (saludo As String, destino As String) =
    ("Hola", "Mundo") ' para acceder a los miembros, usamos los nombres Console.WriteLine("{0} {1}", t2.saludo, t2.destino)

    Ejemplo 4: Definimos una tupla con miembros con nombres, asignando los valores al definirla. Para acceder a los miembros, usamos los nombres.

    ' definimos una tupla con miembros con nombres
    Dim t2 = (saludo:="Hola", destino:="Mundo")
    ' para acceder a los miembros, usamos los nombres
    Console.WriteLine("{0} {1}", t2.saludo, t2.destino)

    Ejemplo 5 (extra): Método que recibe un array de tipo «tupla».

    Este código es un método llamado colorear que recibe un array del tipo (ConsoleColor, String), se procesa cada uno de los elementos del array y se usa el valor del color para indicar el color del valor ForegroundColor (color del texto) de la clase Consola, el contenido del valor String lo usamos para mostrarlo en la consola por medio de WriteLine.

    Con ese código se consiguen salidas en la ventana de la consola como la siguiente:

    tuplasVB_04

    El código del método colorear es el siguiente:

    ''' <summary>
    ''' Colorear la salida de los ejemplos, 
    ''' también usando tuplas ;-)
    ''' Se pasa como argumento 
    ''' un array del tipo (color As ConsoleColor, texto As String)
    ''' </summary>
    ''' <param name=items">un array del tipo (color As ConsoleColor, texto As String)</param>"
    Private Sub colorear(items As (color As ConsoleColor, texto As String)())
        For Each it In items
            Console.ForegroundColor = it.color
            Console.WriteLine(it.texto)
        Next
    
        Console.ForegroundColor = co.Gray
        Console.WriteLine()
    End Sub

    Para usarlo podemos hacer como en el código para el cuarto ejemplo:

    Private Sub ejemplo4()
        colorear({(co.Green, "definimos una tupla con miembros con nombres"),
                  (co.Green, "(asignando los valores al definirla)"),
                  (co.Yellow, "Dim t2 = (saludo:=""Hola"", destino:=""Mundo"")"),
                  (co.Green, "para acceder a los miembros, usamos los nombres"),
                  (co.Yellow, "Console.WriteLine(""{0} {1}"", t2.saludo, t2.destino)")})
    
        ' definimos una tupla con miembros con nombres
        Dim t2 = (saludo:="Hola", destino:="Mundo")
        ' para acceder a los miembros, usamos los nombres
        Console.WriteLine("{0} {1}", t2.saludo, t2.destino)
    
        Console.ReadLine()
    End Sub

    Nota:
    Es curioso, pero resulta que es más fácil definir los parámetros (de tipo array o matriz) directamente en la llamada del método colorear en Visual Basic que en C#.
    En Visual Basic se indica el array del tipo tupla de la siguiente forma:

    colorear({
        (co.Green, «definimos una tupla con miembros con nombres»),

         (co.Green, «(asignando los valores al definirla)»),     (co.Yellow, «Dim t2 = (saludo:=»»Hola»», destino:=»»Mundo»»)»),

         (co.Green, «para acceder a los miembros, usamos los nombres»),

         (co.Yellow, «Console.WriteLine(«»{0} {1}»», t2.saludo, t2.destino)»)})

    Mientras que en C# hay indicar que es un nuevo array:
    colorear(new []{
           (co.Green, «definimos una tupla con miembros con nombres»),
           (co.Green, «(asignando los valores al definirla)»),
           (co.Yellow, «var t2 = (saludo:\»Hola\», destino:\»Mundo\»);»),
           (co.Green, «para acceder a los miembros, usamos los nombres»),
           (co.Yellow, «Console.WriteLine(\»{0} {1}\», t2.saludo, t2.destino);»)});

    Y esto es todo por hoy.
    Bueno, no, más abajo te muestro el código de estos dos últimos códigos para C#.

    Nota:
    En otra ocasión te mostraré más código de ejemplo del uso de tuplas en Visual Basic y C#, seguramente usando funciones que devuelvan tuplas y cómo usar la «inferencia» de los argumentos con nombre… ¿se podrá hacer eso con Visual Basic? sí se puede… pero necesita más explicación, ya que el Visual Studio 2017 no lo compilará y hay que hacer «un tuquillo» para que lo compile. Con C# tampoco lo compila, y también hay que hacer un truco similar al de Visual Basic.
    En realidad no te lo explico aquí porque no lo había probado, entre otras cosas porque no me ha hecho falta; lo de la función que devuelve una tupla si que lo he usado en una aplicación que estoy haciendo actualmente.

    Espero que te sea de utilidad Smile

    Nos vemos.
    Guillermo

    P.S. 09/Dic/18:
    No es un artículo dedicado a las tuplas, pero en el ejemplo que publiqué ayer sobre el Error al guardar datos decimales: El valor del parámetro ‘xxx’ está fuera del intervalo tienes un ejemplo de cómo usar una función que devuelve una tupla.

    Private Function AñadirMiTabla1(valor As Decimal) As (hayError As Boolean, msg As String)

    private (bool hayError, string msg) AñadirMiTabla1(decimal valor)

    P.S.

    Código de uso de Tuplas (Tuples) en C#

    Ejemplo 1: Ejemplo básico de tuplas sin definir los nombres de los miembros:

    // Al definirla de esta forma
    // tenemos una tupla con dos elementos del tipo cadena
    var t1 = ("Hola", "mundo");
    
    // para acceder a los miembros usaremos Item1, Item2
    Console.WriteLine("{0} {1}", t1.Item1, t1.Item2);

    Ejemplo 4: Definimos una tupla con miembros con nombres, asignando los valores al definirla. Para acceder a los miembros, usamos los nombres.

    // definimos una tupla con miembros con nombres
    var t2 = (saludo: "Hola", destino: "Mundo");
    // para acceder a los miembros, usamos los nombres
    Console.WriteLine("{0} {1}", t2.saludo, t2.destino);

    Ejemplo 5 (extra): Método que recibe un array de tipo «tupla».

    Este código es un método llamado colorear que recibe un array del tipo (ConsoleColor, string), se procesa cada uno de los elementos del array y se usa el valor del color para indicar el color del valor ForegroundColor (color del texto) de la clase Consola, el contenido del valor string lo usamos para mostrarlo en la consola por medio de WriteLine.

    Con ese código se consiguen salidas en la ventana de la consola como la siguiente:

    tuplasCS_04

    El código del método colorear es el siguiente:

    /// <summary>
    /// Colorear la salida de los ejemplos,
    /// también usando tuplas ;-)
    /// Se pasa como argumento
    /// un array del tipo (ConsoleColor color, string texto)
    /// </summary>
    /// <param name=items">un array del tipo (ConsoleColor color, string texto)</param>"
    static private void colorear((ConsoleColor color, string texto)[] items)
    {
        foreach (var it in items)
        {
            Console.ForegroundColor = it.color;
            Console.WriteLine(it.texto);
        }
    
        Console.ForegroundColor = co.Gray;
        Console.WriteLine();
    }

    Para usarlo podemos hacer como en el código para el cuarto ejemplo:

    /// <summary>
    /// Definimos una tupla con miembros con nombres
    /// (asignando los valores al definirla)
    /// Para acceder a los miembros, usamos los nombres
    /// </summary>
    static private void ejemplo4()
    {
        //new (co color,string texto)[]
    
        colorear(new []{
              (co.Green, "definimos una tupla con miembros con nombres"),
              (co.Green, "(asignando los valores al definirla)"),
              (co.Yellow, "var t2 = (saludo:\"Hola\", destino:\"Mundo\");"),
              (co.Green, "para acceder a los miembros, usamos los nombres"),
              (co.Yellow, "Console.WriteLine(\"{0} {1}\", t2.saludo, t2.destino);")});
    
        // definimos una tupla con miembros con nombres
        var t2 = (saludo: "Hola", destino: "Mundo");
        // para acceder a los miembros, usamos los nombres
        Console.WriteLine("{0} {1}", t2.saludo, t2.destino);
    
        Console.ReadLine();
    }

    ¡Hasta el siguiente post! Smile