Etiqueta: C#Sharp

Temas relacionados con C#

  • 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

  • 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

  • Números aleatorios con decimales en .NET

    Pues eso… aquí te explicaré cómo generar números aleatorios con decimales y cómo indicar los valores entre los que quieres que estén esos números usando la clase Random de .NET y con ejemplos tanto para Visual Basic .NET como para C# (e incluso para BASIC, bueno… al menos para Visual Basic 6.0 y anteriores).

    Pero primero te contaré la «batallita del Guille» para que sepas el porqué a estas alturas de la vida te explico algo tan «elemental» Winking smile

    Si no te quieres leer la batallita, pues… pasa un poco más abajo que ahí te muestro el código de ejemplo tanto para Visual Basic .NET como para C# e incluso para VB6.

    La batallita del Guille

    Estaba yo el otro día escribiendo un código en el que necesitaba generar dos números aleatorios (en realidad varios).
    Dos de ellos eran números enteros, en esos no tuve mayor problema, ya que tenía este artículo publicado en mi sitio: Random.Next ese incomprendido  y me lo leí, y todo a la perfección… Winking smile

    El problema me surgió al crear los números aleatorios con decimales.
    Yo sabía que usando NextDouble de la clase Random era como tenía que hacerlo (la certeza era porque yo lo decía al final del artículo ese que te he comentado en el párrafo anterior Winking smile).
    Y curiosamente en ese mismo comentario decía que lo más parecido a la función Rnd() de Visual Basic 6.0 era precisamente NextDouble.
    Pero… ¿quieres creerte que ya no me acordaba cómo se usaba la función RND de BASIC? jajajaja, en fin… seguramente serán cosas de la edad o de que en los últimos años no tengo la programación como una de mis tareas diarias… en fin…

    La cuestión es que volvía a buscar en la web (indicando elGuille) cómo usar RND o casi… y me encontré como mi Curso Básico de Programación en Visual Basic, concretamente en las soluciones de la décima entrega, lo explicaba… ¡menos mal que el Guille aún mantiene su sitio después de los 22 años que cumplió hace pocos días! Winking smile

    Generar un número aleatorio con decimales entre dos cifras

    El método NextDouble genera un número que será igual o mayor que 0.0 y menor (pero no igual) que 1.0.
    Por tanto si lo multiplicaras, por ejemplo por 6, generaría un valor que iría desde 0.0 a 5.99.

    Nota:
    En Visual Basic 6.0 (o incluso en VB.NET y si me apuras hasta en C#) se utilizará la función Rnd para hacer el mismo papel que NextDouble, pero con valores de tipo Single en lugar de Double.

    Tal como explico en las respuestas del curso básico, si quieres un número entero entre 20 y 50 debes escribir un código como este (este ejemplo es de VB6, las variables están declaradas en otra parte… supongo)

    T = Int(Rnd * 31) + 20 ‘Número de rascadas, T valdrá de 20 a 50

    Es decir la función Rnd (o el método NextDouble) debes multiplicarlo por  31 (50-20+1) y después añadirle el mínimo (20). De esa forma se genera el rango de valores que queremos usar.
    En ese ejemplo se usa la función Int para convertir el resultado en un número entero, pero recuerda que ¡es código de VB6!

    Ahora veremos ese mismo ejemplo pero haciendo las cosas bien y con .NET.

    El código de ejemplo

    El siguiente código creará un número aleatorio (con decimales) entre 20 y 50 (ambos incluidos).

    Inserta este código en el método Main de una aplicación de consola.

    Código para Visual Basic .NET

    Dim r As New Random()
    
    Dim minimo As Integer = 20
    Dim maximo As Integer = 50
    
    Dim res = (r.NextDouble() * (maximo - minimo + 1)) + minimo
    Console.WriteLine("Un número Double entre {0} y {1} (incluidos)", minimo, maximo)
    Console.WriteLine("(r.NextDouble * ({0} - {1} + 1)) + {1} = {2}", maximo, minimo, res)
    Console.WriteLine()
    
    Console.ReadLine()

    Código para C#

    var r = new Random();
    
    int minimo = 20;
    int maximo = 50;
    
    var res = (r.NextDouble() * (maximo - minimo + 1)) + minimo;
    Console.WriteLine("Un número Double entre {0} y {1} (incluidos)", minimo, maximo);
    Console.WriteLine("(r.NextDouble * ({0} - {1} + 1)) + {1} = {2}", maximo, minimo, res);
    Console.WriteLine();
    
    Console.ReadLine();

    La salida mostrada será algo así:

    numeros_aleatorios_vb_02
    Figura 1. Salida del código de ejemplo

    Casualmente el número generado aleatoriamente es 50 y pico… para que veas que el máximo también se incluye Smile

    Resumiendo

    Para generar un número entre dos valores (ambos incluidos) usa el cálculo siguiente:

    (r.NextDouble() * (maximo – minimo + 1)) + minimo

    o este otro que también hace lo mismo:

    (r.NextDouble() * (minimo – maximo)) + maximo

    Resaltar aquí, que si quieres la misma funcionalidad que el método Next de la clase Random, es decir que el valor generado sea igual o mayor que mínimo pero menor que máximo tendrías que hacerlo de esta forma:

    (r.NextDouble() * (maximo – minimo)) + minimo

    Para finalizar, recordarte que le eches un vistazo a las explicaciones que doy en el artículo que te indiqué al principio:
    Random.Next ese incomprendido

    Espero que te sirva Winking smile

    Nos vemos.
    Guillermo