[Ayuda] Como hacer para validar una text box para q admita solo numeros

Iniciado por estebankpo15, 1 Febrero 2015, 21:57 PM

0 Miembros y 1 Visitante están viendo este tema.

estebankpo15

Hola estoy haciendo un sistema de validaciones para un final de la facultad, la cosa es q tengo una txtbox donde solo se deben ingresar numeros y al precionar guardar tendria que validad que lo q ingrese sea un numero.
Tambien habia pensado en que la textbox solo se puedan escribir numeros.
Alguien sabe alguna manera de solucionar esto?

Eleкtro

Cita de: estebankpo15 en  1 Febrero 2015, 21:57 PMAlguien sabe alguna manera de solucionar esto?

Hay varías maneras.

La primera manera, y también las más eficiente, sería reemplazar el uso de un TextBox para utilizar el control más adecuado a tu situación actual y así seguir buenas prácticas de programación, tienes 2 posibilidades y ambas sin mayores complicaciones:
1) Un control de tipo NumericUpDown para rangos numéricos (ej: 0 - 100).
2) Un control de tipo MaskedTextbox para máscaras numéricas (ej: nnn.nnn.nnn.nnn).

Ahora bien, supongamos que por el motivo que sea prefieres omitir el consejo de arriba y seguir utilizando un TextBox, pues bien, soluciones:

1) Utilizar una expresión regular ("^\d+$") y evaluarla o utilizar los métodos de validación del Type Char, suscribiéndote al evento KeyPress para comprobar si el caracter es un número, pero esto sería una solución horrible ya que estariamos descuidando otros factores a tener en cuenta, de todas formas mostraré un ejemplo breve por si quieres ir a lo sencillo:
Código (vbnet) [Seleccionar]
   ''' <summary>
   ''' Handles the KeyPress event of the TextBox1 control.
   ''' </summary>
   ''' <param name="sender">The source of the event.</param>
   ''' <param name="e">The <see cref="KeyPressEventArgs"/> instance containing the event data.</param>
   Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As KeyPressEventArgs) _
   Handles TextBox1.KeyPress

       e.Handled = Not Char.IsNumber(e.KeyChar)

   End Sub


2) Cómo he dicho la solución anterior es horrible, ¿por qué?, por que para evitar completamente que se puede añadir "X" caracter en un TextBox corriente, debes tener varias cosas más en cuenta, como el menú contextual (Edit menu), los atajos de teclado Windows (System-wide Hotkeys), y la característica de soltar y arrastrar (Drag&Drop) en caso de que desees añadirle dicha funcionalidad.

Así pues, otra manera que aportaría mayor eficiencia, libertad, y personalización, sería definir un set de caracteres permitidos, y cancelar la escritura del caracter en el evento KeyPress cuando dicho caracter no se encuentre dentro de los caracteres permitidos:

Para ello he implementado el uso de dicha técnica desarrollando un user-control (el cual se puede mejorar en muchos sentidos, ya que no le puse demasiado empeño en la elaboración del código).

Modo de empleo:
Código (vbnet) [Seleccionar]
Imports WindowsApplication1.ElektroTextBox

Public Class TestForm

   Private WithEvents etb As New ElektroTextBox

   Private Sub TestForm_Load() Handles MyBase.Load

       With Me.etb
           .AllowDrop = True
           .DisableEditMenu = True
           .CurrentCharSet = CharSet.StandardAlphabetic Or
                             CharSet.StandardSymbols Or
                             CharSet.Numeric

       End With

#If DEBUG Then
       Debug.WriteLine("ElektroTextBox has been initialized...")
       Debug.WriteLine(String.Format("Current CharSet Int: {0}", CStr(etb.CurrentCharSet)))
       Debug.WriteLine(String.Format("Current CharSet Str: {0}", etb.CurrentCharSet))
       Debug.WriteLine(String.Format("CharSet Characters : {0}", String.Join(String.Empty, etb.CurrentCharSetChars)))
#End If

       MyBase.Controls.Add(Me.etb)

   End Sub

End Class


Source:
Nota: Las características del menú contextual se pueden manejar también con los mensajes de Windows que procesa la ventana, WM_COPY, WM_CUT, y WM_PASTE, pero he preferido omitir la intercepción y el procesamiento de mensajes de Windows para no cargar más de la cuenta el user-control con operaciones innecesarias (y tambien porque como ya dije no le he puesto tanto empeño para su elaboración).

Código (vbnet) [Seleccionar]
' ***********************************************************************
' Author   : Elektro
' Modified : 02-February-2015
' ***********************************************************************
' <copyright file="ElektroTextBox.vb" company="Elektro Studios">
'     Copyright (c) Elektro Studios. All rights reserved.
' </copyright>
' ***********************************************************************

#Region " Imports "

Imports System.ComponentModel

#End Region

''' <summary>
''' An extended TextBox with character validation capabilities.
''' </summary>
Public NotInheritable Class ElektroTextBox : Inherits TextBox

#Region " Properties "

   ''' <summary>
   ''' Gets or sets a value indicating whether
   ''' the default <see cref="ContextMenuStrip"/> for this <see cref="ElektroTextBox"/> instance is disabled.
   ''' </summary>
   ''' <value>
   ''' <c>true</c> if <see cref="ContextMenuStrip"/> is disabled for this <see cref="ElektroTextBox"/> instance;
   ''' <c>false</c> otherwise.</value>
   Public Property DisableEditMenu As Boolean = False

   ''' <summary>
   ''' An empty <see cref="ContextMenuStrip"/> that replaces the default <see cref="ContextMenuStrip"/>
   ''' when <see cref="DisableEditMenu"/> property is set to <c>true</c>.
   ''' of this <see cref="ElektroTextBox"/> instance.
   ''' </summary>
   Private ReadOnly emptynessContextMenuStrip As ContextMenuStrip

   ''' <summary>
   ''' Gets or sets the character-set that contains the allowed characters to fill this <see cref="ElektroTextBox"/> instance.
   ''' </summary>
   ''' <value>The character-set that contains the allowed characters to fill this <see cref="ElektroTextBox"/> instance.</value>
   <Description("The characters that are allowed to fill this ElektroTextBox")>
   Public Property CurrentCharSet As CharSet
       Get
           Return Me.currentCharSet1
       End Get
       Set(ByVal value As CharSet)
           Me.currentCharSet1 = value
           Me.currentCharSetChars1 = Me.GetCharSetChars(value)
       End Set
   End Property
   ''' <summary>
   ''' The character-set that contains the allowed characters to fill this <see cref="ElektroTextBox"/> instance.
   ''' </summary>
   Private currentCharSet1 As CharSet = CharSet.StandardAlphabetic Or CharSet.StandardSymbols Or CharSet.Numeric

   ''' <summary>
   ''' Gets the characters of the current character-set.
   ''' </summary>
   ''' <value>The characters of the current character-set.</value>
   Public ReadOnly Property CurrentCharSetChars As IEnumerable(Of Char)
       Get
           Return Me.currentCharSetChars1
       End Get
   End Property
   ''' <summary>
   ''' The characters of the current character-set.
   ''' </summary>
   Private currentCharSetChars1 As IEnumerable(Of Char) = Me.GetCharSetChars(Me.currentCharSet1)

   ''' <summary>
   ''' Determines whether a pasting operation is requested.
   ''' </summary>
   Private isPasteRequested As Boolean = False

   ''' <summary>
   ''' Determines whether the 'Enter' key is requested.
   ''' </summary>
   Private isEnterKeyRequested As Boolean = False

   ''' <summary>
   ''' Determines whether the 'Backspace' key is requested.
   ''' </summary>
   Private isBackspacekeyRequested As Boolean = False

   ''' <summary>
   ''' Determines whether an unknown key is requested.
   ''' </summary>
   Private isUnknownKeyRequested As Boolean = False

   ''' <summary>
   ''' Contains pre-defined <see cref="ElektroTextBox"/> character sets.
   ''' </summary>
   Public NotInheritable Class CharSets

       ''' <summary>
       ''' Gets the standard alphabetic character set.
       ''' </summary>
       ''' <value>The standard alphabetic character set.</value>
       Public Shared ReadOnly Property CharSetStandardAlpha As IEnumerable(Of Char)
           Get
               Return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
           End Get
       End Property

       ''' <summary>
       ''' Gets the standard symbols character set.
       ''' </summary>
       ''' <value>The standard symbols character set.</value>
       Public Shared ReadOnly Property CharSetStandardSymbols As IEnumerable(Of Char)
           Get
               Return """|@·#$~%&¬/\()[]{}<>?!,;.:'¨^-_+=*"
           End Get
       End Property

       ''' <summary>
       ''' Gets the numerical character set.
       ''' </summary>
       ''' <value>The numerical character set.</value>
       Public Shared ReadOnly Property CharSetNumeric As IEnumerable(Of Char)
           Get
               Return "1234567890"
           End Get
       End Property

       ''' <summary>
       ''' Gets the Spanish alphabetic character set.
       ''' </summary>
       ''' <value>The Spanish alphabetic character set.</value>
       Public Shared ReadOnly Property CharSetSpanishAlpha As IEnumerable(Of Char)
           Get
               Return CharSetStandardAlpha.Concat("ñáéíóúàèìòùäëïöüÑÁÉÍÓÚÀÈÌÒÙÄËÏÖÜ")
           End Get
       End Property

       ''' <summary>
       ''' Gets the Spanish symbols character set.
       ''' </summary>
       ''' <value>The Spanish symbols character set.</value>
       Public Shared ReadOnly Property CharSetSpanishSymbols As IEnumerable(Of Char)
           Get
               Return CharSetStandardSymbols.Concat("ºª¿¡`´€")
           End Get
       End Property

       ''' <summary>
       ''' Gets the Catalonian alphabetic character set.
       ''' </summary>
       ''' <value>The Catalonian alphabetic character set.</value>
       Public Shared ReadOnly Property CharSetCatalonianAlpha As IEnumerable(Of Char)
           Get
               Return CharSetStandardAlpha.Concat("çáéíóúàèìòùäëïöüÇÁÉÍÓÚÀÈÌÒÙÄËÏÖÜ")
           End Get
       End Property

       ''' <summary>
       ''' Gets the Catalonian symbols character set.
       ''' </summary>
       ''' <value>The Catalonian symbols character set.</value>
       Public Shared ReadOnly Property CharSetCatalonianSymbols As IEnumerable(Of Char)
           Get
               Return CharSetSpanishSymbols
           End Get
       End Property

       ''' <summary>
       ''' Gets the roman numerals characters set.
       ''' </summary>
       ''' <value>The roman numerals characters set.</value>
       Public Shared ReadOnly Property CharSetRomanNumerals As IEnumerable(Of Char)
           Get
               Return "IVXLCDM"
           End Get
       End Property

   End Class

#End Region

#Region " Enumerations "

   ''' <summary>
   ''' Specifies a <see cref="ElektroTextBox"/> character set.
   ''' These values can be combined.
   ''' </summary>
   <FlagsAttribute>
   Public Enum CharSet As Integer

       ''' <summary>
       ''' Any character set.
       ''' This will disable any character typing on the <see cref="ElektroTextBox"/> instance.
       ''' </summary>
       None = 0

       ''' <summary>
       ''' Standard alphabetic characters.
       ''' </summary>
       StandardAlphabetic = 1

       ''' <summary>
       ''' Standard symbol characters.
       ''' </summary>
       StandardSymbols = 2

       ''' <summary>
       ''' Numeric characters.
       ''' </summary>
       Numeric = 4

       ''' <summary>
       ''' Spanish alphabetic characters.
       ''' </summary>
       SpanishAlphabetic = 8

       ''' <summary>
       ''' Spanish symbol characters.
       ''' </summary>
       SpanishSymbols = 16

       ''' <summary>
       ''' Catalonian alphabetic characters.
       ''' </summary>
       CatalonianAlphabetic = 32

       ''' <summary>
       ''' Catalonian symbol characters.
       ''' </summary>
       CatalonianSymbols = 64

       ''' <summary>
       ''' Roman numerals characters.
       ''' </summary>
       RomanNumerals = 128

   End Enum

#End Region

#Region " Constructors "

   ''' <summary>
   ''' Initializes a new instance of the <see cref="ElektroTextBox"/> class.
   ''' </summary>
   Public Sub New()
       Me.emptynessContextMenuStrip = New ContextMenuStrip
   End Sub

#End Region

#Region " Overriden Events "

   ''' <summary>
   ''' Raises the <see cref="E:Control.Enter"/> event.
   ''' </summary>
   ''' <param name="e">An <see cref="T:EventArgs"/> that contains the event data.</param>
   Protected Overrides Sub OnEnter(ByVal e As EventArgs)

       Me.ToggleEditMenu(Me.DisableEditMenu)
       MyBase.OnEnter(e)

   End Sub

   ''' <summary>
   ''' Raises the <see cref="E:Control.MouseEnter"/> event.
   ''' </summary>
   ''' <param name="e">An <see cref="T:EventArgs" /> that contains the event data.</param>
   Protected Overrides Sub OnMouseEnter(ByVal e As EventArgs)

       Me.ToggleEditMenu(Me.DisableEditMenu)
       MyBase.OnMouseEnter(e)

   End Sub

   ''' <summary>
   ''' Raises the <see cref="E:Control.KeyDown"/> event.
   ''' </summary>
   ''' <param name="e">A <see cref="T:KeyEventArgs"/> that contains the event data.</param>
   Protected Overrides Sub OnKeyDown(ByVal e As KeyEventArgs)

       If (e.KeyCode = Keys.Enter) Then ' Enter key.
           ' Let handle the 'Enter' key on 'KeyPress' event for proper evaluation.
           Me.isEnterKeyRequested = True

       ElseIf (e.KeyCode = Keys.Back) Then ' Backspace key.
           ' Let handle the 'Enter' key on 'KeyPress' event for proper evaluation..
           Me.isBackspacekeyRequested = True

       ElseIf (e.KeyCode = Keys.C) AndAlso (e.Modifiers = Keys.Control) Then ' CTRL+C hotkey.
           ' Allow to copy text.
           e.Handled = False
           e.SuppressKeyPress = True
           MyBase.Copy()

       ElseIf (e.KeyCode = Keys.X) AndAlso (e.Modifiers = Keys.Control) Then ' CTRL+X hotkey.
           ' Allow to cut text.
           e.Handled = False
           e.SuppressKeyPress = True
           MyBase.Cut()

       ElseIf (e.KeyCode = Keys.V) AndAlso (e.Modifiers = Keys.Control) Then ' CTRL+V hotkey.
           ' Let handle the text pasting on 'KeyPress' event for proper character(s) evaluation.
           Me.isPasteRequested = True

       Else ' Unhandled character.
           ' Let handle the unknown char on 'KeyPress' event for proper character evaluation.
           Me.isUnknownKeyRequested = True

       End If

#If DEBUG Then ' Helper.
       Debug.WriteLine(String.Format("Modifiers:{0} KeyCode:{1} KeyData:{2} KeyValue:{3} ",
                                     e.Modifiers.ToString,
                                     e.KeyCode.ToString,
                                     e.KeyData.ToString,
                                     e.KeyValue.ToString))
#End If

       MyBase.OnKeyDown(e)

   End Sub

   ''' <summary>
   ''' Raises the <see cref="E:Control.KeyPress"/> event.
   ''' </summary>
   ''' <param name="e">A <see cref="T:KeyPressEventArgs"/> that contains the event data.</param>
   Protected Overrides Sub OnKeyPress(ByVal e As KeyPressEventArgs)

       If isPasteRequested Then
           ' Allow to paste text only if all characters are allowed characters.
           e.Handled = Not Me.StringHasNonAllowedChars(Clipboard.GetText, Me.currentCharSetChars1)
           Me.isPasteRequested = False

       ElseIf isBackspacekeyRequested Then
           ' Allow character deletion.
           e.Handled = False
           Me.isBackspacekeyRequested = False

       ElseIf isEnterKeyRequested Then
           ' Allow the effects of Enter key.
           e.Handled = False
           Me.isEnterKeyRequested = False

       ElseIf isUnknownKeyRequested Then
           ' Allow unknown character only if it's an allowed character.
           e.Handled = Not Me.StringHasNonAllowedChars({Convert.ToChar(e.KeyChar)}, Me.currentCharSetChars1)
           Me.isUnknownKeyRequested = False

       End If

       MyBase.OnKeyPress(e)

   End Sub

   ''' <summary>
   ''' Raises the <see cref="E:Control.DragEnter"/> event.
   ''' </summary>
   ''' <param name="drgevent">A <see cref="T:DragEventArgs"/> that contains the event data.</param>
   Protected Overrides Sub OnDragEnter(ByVal drgevent As DragEventArgs)

       If MyBase.AllowDrop Then

           Select Case True

               Case drgevent.Data.GetDataPresent(DataFormats.Text) ' ANSI text.
                   drgevent.Effect = DragDropEffects.Copy ' Drop text from dragged source.

               Case Else
                   ' Do Nothing.

           End Select

       End If

       MyBase.OnDragEnter(drgevent)

   End Sub

   ''' <summary>
   ''' Raises the <see cref="E:Control.DragDrop"/> event.
   ''' </summary>
   ''' <param name="drgevent">A <see cref="T:DragEventArgs"/> that contains the event data.</param>
   Protected Overrides Sub OnDragDrop(ByVal drgevent As DragEventArgs)

       If MyBase.AllowDrop Then

           Select Case True

               Case drgevent.Data.GetDataPresent(DataFormats.Text) ' ANSI text.
                   Dim dropString As String = DirectCast(drgevent.Data.GetData(DataFormats.Text), String)

                   ' Allow text drop only if all characters are numeric.
                   If Me.StringHasNonAllowedChars(dropString, Me.currentCharSetChars1) Then
                       MyBase.Text = dropString
                   End If

               Case Else
                   ' Do Nothing.

           End Select

       End If

       MyBase.OnDragDrop(drgevent)

   End Sub

#End Region

#Region " Private Methods "

   ''' <summary>
   ''' Toggles the edit menu visibility.
   ''' </summary>
   ''' <param name="enable">
   ''' If set to <c>true</c>, restores the default <see cref="ContextMenuStrip"/> for this <see cref="ElektroTextBox"/> instance.
   ''' </param>
   Private Sub ToggleEditMenu(ByVal enable As Boolean)

       If (enable) AndAlso (MyBase.ContextMenuStrip Is Nothing) Then
           ' Disable default Copy/Cut/Paste contextmenu.
           MyBase.ContextMenuStrip = Me.emptynessContextMenuStrip

       ElseIf Not (enable) AndAlso (MyBase.ContextMenuStrip IsNot Nothing) Then
           ' Restore default edit contextmenu.
           MyBase.ContextMenuStrip = Nothing

       Else
           ' Do Nothing.

       End If

   End Sub

   ''' <summary>
   ''' Gets the characters of a <see cref="CharSet"/>.
   ''' </summary>
   ''' <param name="charSet">The <see cref="CharSet"/>.</param>
   ''' <returns>The characters of a <see cref="CharSet"/>.</returns>
   Private Function GetCharSetChars(ByVal charSet As CharSet) As IEnumerable(Of Char)

       Dim chars As IEnumerable(Of Char) = String.Empty

       If charSet.HasFlag(charSet.None) Then
           ' Do Nothing.
       End If

       If charSet.HasFlag(charSet.StandardAlphabetic) Then
           chars = chars.Concat(CharSets.CharSetStandardAlpha)
       End If

       If charSet.HasFlag(charSet.StandardSymbols) Then
           chars = chars.Concat(CharSets.CharSetStandardSymbols)
       End If

       If charSet.HasFlag(charSet.Numeric) Then
           chars = chars.Concat(CharSets.CharSetNumeric)
       End If

       If charSet.HasFlag(charSet.SpanishAlphabetic) Then
           chars = chars.Concat(CharSets.CharSetSpanishAlpha)
       End If

       If charSet.HasFlag(charSet.SpanishSymbols) Then
           chars = chars.Concat(CharSets.CharSetSpanishSymbols)
       End If

       If charSet.HasFlag(charSet.CatalonianAlphabetic) Then
           chars = chars.Concat(CharSets.CharSetCatalonianAlpha)
       End If

       If charSet.HasFlag(charSet.CatalonianSymbols) Then
           chars = chars.Concat(CharSets.CharSetCatalonianSymbols)
       End If

       If charSet.HasFlag(charSet.RomanNumerals) Then
           chars = chars.Concat(CharSets.CharSetRomanNumerals)
       End If

       Return (From c As Char In chars Order By c.ToString Ascending Distinct)

   End Function

   ''' <summary>
   ''' Determines whether the specified string has non allowed characters for this <see cref="ElektroTextBox"/> instance.
   ''' </summary>
   ''' <param name="characters">The characters that will be evaluated.</param>
   ''' <param name="allowedChars">The allowed characters.</param>
   ''' <returns><c>true</c> if all the characters of the specified string satisfy the condition;
   ''' <c>false</c> otherwise.</returns>
   Private Function StringHasNonAllowedChars(ByVal characters As IEnumerable(Of Char),
                                             ByVal allowedChars As IEnumerable(Of Char)) As Boolean

       Return characters.All(Function(c As Char)
                                 Return allowedChars.Contains(c, Nothing)
                             End Function)

   End Function

#End Region

End Class


Saludos.








__Alvaro 2015__

Puedes utilizar la Función "IsNumeric", ejemplo:

Código (vbnet) [Seleccionar]


Dim cadena As String = ""

Console.WriteLine("Ingrese un numero:")
cadena = Console.ReadLine()

If IsNumeric(cadena) Then
    Console.WriteLine("Es numero")
Else
    Console.WriteLine("No es numero")
End If
Console.WriteLine("Presione enter para continuar..")
Console.ReadLine()



Saludos  ::)
"Pasión por la programación"

Eleкtro

Cita de: __Alvaro 2015__ en  6 Febrero 2015, 06:23 AM
Puedes utilizar la Función "IsNumeric", ejemplo:

Lo que sugieres son malas prácticas de programación, al utilizar un wrapper de VB6.

¿Has leido mi post?, arriba puse un ejemplo sencillo de como usar su equivalente en .Net, utilizando el método Char.IsNumber()

Por otor lado, para comrprobar si un String es numérico, el equivalente de "IsNumeric" en .Net sería utilizar el método Parse/TryParse del Datatype específico, por ejemplo:

Código (vbnet) [Seleccionar]
If Integer.TryParse("123", New Integer) Then
' Es un número.
End If


...Pero eso es algo innecesario al igual que la función IsNumeric, ya que la pregunta no requiere comprobar un String, sino un único Char.

Este comentario es con la intención de orientar a aquellas personas que sugieren la utilización de la función IsNumeric, al igual que Left, Right, y todas esas cosas obsoletas, Porfavor, eviten su utilización.

Saludos!








__Alvaro 2015__

Citar
Lo que sugieres son malas prácticas de programación, al utilizar un wrapper de VB6.

Eso hoy en día es una leyenda, antes si era cierto, por que el CLR de VB6 ejecutaba mucho código basura, posteriormente se desarrollo (por así decirlo, .NET), y se determino, que un "wrapper" siendo un objeto a diferencia de un dato primitivo te brinda métodos que son de gran utilidad, para el manejo de primitivos.
Por esta razón, es que se utilizan esta y otras funciones en la gran mayoría de los lenguajes, sin considerarlos "deprecated".

Igual estoy a favor de que se brinden alternativas, y admiro tu esmerada respuesta Elektro.

Citar
...Pero eso es algo innecesario al igual que la función IsNumeric, ya que la pregunta no requiere comprobar un String, sino un único Char.

El evento de escucha "KeyPress" no siempre funciona bien.

Saludos.
"Pasión por la programación"

luis456

Yo lo solucione de esta manera espero te sirva


Código (vbnet) [Seleccionar]
  Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
        solonumeros(e)
        If e.KeyChar = ChrW(Keys.Enter) Then
            e.Handled = True
            SendKeys.Send("{TAB}")
        End If
    End Sub



luis

Que tu sabiduria no sea motivo de Humillacion para los demas

Eleкtro

Cita de: __Alvaro 2015__ en  6 Febrero 2015, 08:12 AM
Eso hoy en día es una leyenda, antes si era cierto, por que el CLR de VB6 ejecutaba mucho código basura, posteriormente se desarrollo (por así decirlo, .NET), y se determino, que un "wrapper" siendo un objeto a diferencia de un dato primitivo te brinda métodos que son de gran utilidad, para el manejo de primitivos.
Por esta razón, es que se utilizan esta y otras funciones en la gran mayoría de los lenguajes, sin considerarlos "deprecated".

No soy una persona de afirmar leyendas, ya que no es ninguna leyenda, es tal y como es;
la razón de que Microsoft decidiese desarrollar ese namespace fue con la finalidad de que a los desarrolladores del antiguo VB6 les fuera más comodo actualizarse a VB.Net, hallando así los mismos métodos que utilizaban en el antiguo VB6 al sentirse familiriazados con éstos, un motivo comprensible, pero eso no significa que lo correcto sea usarlos, ni que deban ser usados.

Obviamente al denominar como "obsoleto" los miembros de ese namespace no lo digo porque esté escrito en VB6, ya que es todo código .Net, y algunas de las llamadas de los métodos del namespace Microsoft.VisualBasic son simplemente wrappers de funcionalidades de otros métodos existentes de la librería de classes de .Net Framework, lo que podemos denominar "puro código .Net", pero otras muchas NO lo son, son "puro código basura".

Ya que para casi todos los métodos/funciones del namespace VisualBasic, existen versiones mucho más robustas en el resto de la librería de classes de .Net Framework.
Un ejemplo de esto sería la función "Val", comparándola con la función "TryParse" de un Datatype específico.

Los métodos/funciones del namespace VisualBasic usan técnicas consideradas deprecadas por el propio Microsoft (bueno, y por "la industria de la programación"), es decir, malas prácticas de programación , como por ejemplo el uso del GOTO y los Labels al proporcionar una estructura insegura al código,
para no dejarme nada en el tintero, esto es solo un ejemplo de dichas malas prácticas, y es algo que obviamente también se utiliza en el namespace System (lo nombro al ser el namespace que usaré para la siguiente comparación de abajo), pero con una menor frecuencia en al relación de veces usada * cantitad de miembros, siendo 155 veces en el namespace VisualBasic en 179 archivos desamblados, es decir, cerca del 87% de las classes utilizan esta mala práctica, y 915 veces en el namespace System en 1.681 archivos desamblados, alrededor de un 54% de las classes, pero vuelvo a recordar que solo era un ejemplo, no nos fijemos solo en este aspecto, ya que hay otras cosas del namespace VisualBasic que son "basura".

Y por esos motivos no es lo más conveniente usar esos wrappers.

Te mostraré algo, haciendo uso de la técnica Reflection, estas son las instrucciones de la función "Val" del namespace Microsoft.VisualBasic,

(omitiendo las instrucciones de varios métodos más como ChrW, etc, para no hacer más largo este post)

Código (vbnet) [Seleccionar]
Public Shared Function Val(ByVal InputStr As String) As Double
   Dim ch As Char
   Dim num As Integer
   Dim num2 As Integer
   Dim num3 As Integer
   Dim length As Integer
   Dim num8 As Double
   If (InputStr Is Nothing) Then
       length = 0
   Else
       length = InputStr.Length
   End If
   Dim num4 As Integer = 0
   Do While (num4 < length)
       ch = InputStr.Chars(num4)
       Select Case ch
           Case ((ChrW(9) AndAlso ChrW(10)) AndAlso ((ChrW(13) AndAlso " "c) AndAlso ChrW(12288)))
               Exit Select
       End Select
       num4 += 1
   Loop
   If (num4 >= length) Then
       Return 0
   End If
   ch = InputStr.Chars(num4)
   If (ch = "&"c) Then
       Return Conversion.HexOrOctValue(InputStr, (num4 + 1))
   End If
   Dim flag As Boolean = False
   Dim flag2 As Boolean = False
   Dim flag3 As Boolean = False
   Dim y As Double = 0
   ch = InputStr.Chars(num4)
   Select Case ch
       Case "-"c
           flag3 = True
           num4 += 1
           Exit Select
       Case "+"c
           num4 += 1
           Exit Select
   End Select
   Do While (num4 < length)
       ch = InputStr.Chars(num4)
       Dim ch3 As Char = ch
       If (((ch3 = ChrW(9)) OrElse (ch3 = ChrW(10))) OrElse (((ch3 = ChrW(13)) OrElse (ch3 = " "c)) OrElse (ch3 = ChrW(12288)))) Then
           num4 += 1
       Else
           If (ch3 = "0"c) Then
               If ((num <> 0) OrElse flag) Then
                   num8 = (((num8 * 10) + CDbl(ch)) - 48)
                   num4 += 1
                   num += 1
               Else
                   num4 += 1
               End If
               Continue Do
           End If
           If ((ch3 >= "1"c) AndAlso (ch3 <= "9"c)) Then
               num8 = (((num8 * 10) + CDbl(ch)) - 48)
               num4 += 1
               num += 1
           Else
               If (ch3 = "."c) Then
                   num4 += 1
                   If flag Then
                       Exit Do
                   End If
                   flag = True
                   num3 = num
                   Continue Do
               End If
               If (((ch3 = "e"c) OrElse (ch3 = "E"c)) OrElse ((ch3 = "d"c) OrElse (ch3 = "D"c))) Then
                   flag2 = True
                   num4 += 1
               End If
               Exit Do
           End If
       End If
   Loop
   If flag Then
       num2 = (num - num3)
   End If
   If Not flag2 Then
       If (flag AndAlso (num2 <> 0)) Then
           num8 = (num8 / Math.Pow(10, CDbl(num2)))
       End If
   Else
       Dim flag4 As Boolean = False
       Dim flag5 As Boolean = False
       Do While (num4 < length)
           ch = InputStr.Chars(num4)
           Dim ch4 As Char = ch
           If (((ch4 = ChrW(9)) OrElse (ch4 = ChrW(10))) OrElse (((ch4 = ChrW(13)) OrElse (ch4 = " "c)) OrElse (ch4 = ChrW(12288)))) Then
               num4 += 1
           ElseIf ((ch4 >= "0"c) AndAlso (ch4 <= "9"c)) Then
               y = (((y * 10) + CDbl(ch)) - 48)
               num4 += 1
           Else
               If (ch4 = "+"c) Then
                   If flag4 Then
                       Exit Do
                   End If
                   flag4 = True
                   num4 += 1
                   Continue Do
               End If
               If ((ch4 <> "-"c) OrElse flag4) Then
                   Exit Do
               End If
               flag4 = True
               flag5 = True
               num4 += 1
           End If
       Loop
       If flag5 Then
           y = (y + num2)
           num8 = (num8 * Math.Pow(10, -y))
       Else
           y = (y - num2)
           num8 = (num8 * Math.Pow(10, y))
       End If
   End If
   If Double.IsInfinity(num8) Then
       Throw ExceptionUtils.VbMakeException(6)
   End If
   If flag3 Then
       num8 = -num8
   End If
   Select Case ch
       Case "%"c
           If (num2 > 0) Then
               Throw ExceptionUtils.VbMakeException(13)
           End If
           Return CDbl(CShort(Math.Round(num8)))
       Case "&"c
           If (num2 > 0) Then
               Throw ExceptionUtils.VbMakeException(13)
           End If
           Return CDbl(CInt(Math.Round(num8)))
       Case "!"c
           Return CDbl(CSng(num8))
       Case "@"c
           Return Convert.ToDouble(New Decimal(num8))
   End Select
   Return num8
End Function


Y estas son las de la función "IsNumeric" del mismo namespace:
Código (vbnet) [Seleccionar]
Public Shared Function IsNumeric(ByVal expression As Object) As Boolean
   Dim num As Double
   Dim convertible As IConvertible = TryCast(expression,IConvertible)
   If (convertible Is Nothing) Then
       Dim chArray As Char() = TryCast(expression,Char())
       If (chArray Is Nothing) Then
           Return False
       End If
       expression = New String(chArray)
   End If
   Dim typeCode As TypeCode = convertible.GetTypeCode
   If ((typeCode <> TypeCode.String) AndAlso (typeCode <> TypeCode.Char)) Then
       Return Information.IsOldNumericTypeCode(typeCode)
   End If
   Dim str As String = convertible.ToString(Nothing)
   Try
       Dim num2 As Long
       If Utils.IsHexOrOctValue(str, num2) Then
           Return True
       End If
   Catch exception As StackOverflowException
       Throw exception
   Catch exception2 As OutOfMemoryException
       Throw exception2
   Catch exception3 As ThreadAbortException
       Throw exception3
   Catch exception6 As Exception
       Return False
   End Try
   Return DoubleType.TryParse(str, num)
End Function

Friend Shared Function IsHexOrOctValue(ByVal Value As String, ByRef i64Value As Long) As Boolean
   Dim num As Integer
   Dim length As Integer = Value.Length
   Do While (num < length)
       Dim ch As Char = Value.Chars(num)
       If ((ch = "&"c) AndAlso ((num + 2) < length)) Then
           ch = Char.ToLower(Value.Chars((num + 1)), CultureInfo.InvariantCulture)
           Dim str As String = Utils.ToHalfwidthNumbers(Value.Substring((num + 2)), Utils.GetCultureInfo)
           Select Case ch
               Case "h"c
                   i64Value = Convert.ToInt64(str, &H10)
                   goto Label_0087
               Case "o"c
                   i64Value = Convert.ToInt64(str, 8)
                   goto Label_0087
           End Select
           Throw New FormatException
       End If
       If ((ch <> " "c) AndAlso (ch <> ChrW(12288))) Then
           Return False
       End If
       num += 1
   Loop
   Return False
Label_0087:
   Return True
End Function



Mientras que esto son las instrucciones de la función "Double.TryParse" dentro del namespace System:

Código (vbnet) [Seleccionar]
<__DynamicallyInvokable> _
Public Shared Function TryParse(ByVal s As String, <Out> ByRef result As Double) As Boolean
   Return Double.TryParse(s, (NumberStyles.Float Or NumberStyles.AllowThousands), NumberFormatInfo.CurrentInfo, result)
End Function

Private Shared Function TryParse(ByVal s As String, ByVal style As NumberStyles, ByVal info As NumberFormatInfo, <Out> ByRef result As Double) As Boolean
   If (s Is Nothing) Then
       result = 0
       Return False
   End If
   If Not Number.TryParseDouble(s, style, info, result) Then
       Dim str As String = s.Trim
       If Not str.Equals(info.PositiveInfinitySymbol) Then
           If Not str.Equals(info.NegativeInfinitySymbol) Then
               If Not str.Equals(info.NaNSymbol) Then
                   Return False
               End If
               result = Double.NaN
           Else
               result = Double.NegativeInfinity
           End If
       Else
           result = Double.PositiveInfinity
       End If
   End If
   Return True
End Function

<SecuritySafeCritical> _
Friend Shared Function TryParseDouble(ByVal value As String, ByVal options As NumberStyles, ByVal numfmt As NumberFormatInfo, <Out> ByRef result As Double) As Boolean
   Dim stackBuffer As Byte* = stackalloc Byte[DirectCast(NumberBuffer.NumberBufferBytes, IntPtr)]
   Dim number As New NumberBuffer(stackBuffer)
   result = 0
   If Not Number.TryStringToNumber(value, options, number, numfmt, False) Then
       Return False
   End If
   If Not Number.NumberBufferToDouble(number.PackForNative, result) Then
       Return False
   End If
   Return True
End Function

<TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")> _
Friend Shared Function TryStringToNumber(ByVal str As String, ByVal options As NumberStyles, ByRef number As NumberBuffer, ByVal numfmt As NumberFormatInfo, ByVal parseDecimal As Boolean) As Boolean
   Return Number.TryStringToNumber(str, options, number, Nothing, numfmt, parseDecimal)
End Function

<SecuritySafeCritical, FriendAccessAllowed> _
Friend Shared Function TryStringToNumber(ByVal str As String, ByVal options As NumberStyles, ByRef number As NumberBuffer, ByVal sb As StringBuilder, ByVal numfmt As NumberFormatInfo, ByVal parseDecimal As Boolean) As Boolean
   If (str Is Nothing) Then
       Return False
   End If
   Dim str2 As Char*
   Fixed str2 = DirectCast(str, Char*)
       Dim chPtr As Char* = str2
       Dim chPtr2 As Char* = chPtr
       If (Not Number.ParseNumber(chPtr2, options, number, sb, numfmt, parseDecimal) OrElse ((CLng(((chPtr2 - chPtr) / 2)) < str.Length) AndAlso Not Number.TrailingZeros(str, CInt(CLng(((chPtr2 - chPtr) / 2)))))) Then
           Return False
       End If
   End Fixed
   Return True
End Function

<SecurityCritical> _
Private Shared Function ParseNumber(ByRef str As Char*, ByVal options As NumberStyles, ByRef number As NumberBuffer, ByVal sb As StringBuilder, ByVal numfmt As NumberFormatInfo, ByVal parseDecimal As Boolean) As Boolean
   Dim currencyDecimalSeparator As String
   Dim currencyGroupSeparator As String
   Dim chPtr2 As Char*
   number.scale = 0
   number.sign = False
   Dim currencySymbol As String = Nothing
   Dim ansiCurrencySymbol As String = Nothing
   Dim numberDecimalSeparator As String = Nothing
   Dim numberGroupSeparator As String = Nothing
   Dim flag As Boolean = False
   If ((options And NumberStyles.AllowCurrencySymbol) <> NumberStyles.None) Then
       currencySymbol = numfmt.CurrencySymbol
       If (Not numfmt.ansiCurrencySymbol Is Nothing) Then
           ansiCurrencySymbol = numfmt.ansiCurrencySymbol
       End If
       numberDecimalSeparator = numfmt.NumberDecimalSeparator
       numberGroupSeparator = numfmt.NumberGroupSeparator
       currencyDecimalSeparator = numfmt.CurrencyDecimalSeparator
       currencyGroupSeparator = numfmt.CurrencyGroupSeparator
       flag = True
   Else
       currencyDecimalSeparator = numfmt.NumberDecimalSeparator
       currencyGroupSeparator = numfmt.NumberGroupSeparator
   End If
   Dim num As Integer = 0
   Dim flag2 As Boolean = False
   Dim flag3 As Boolean = (Not sb Is Nothing)
   Dim flag4 As Boolean = (flag3 AndAlso ((options And NumberStyles.AllowHexSpecifier) <> NumberStyles.None))
   Dim num2 As Integer = If(flag3, &H7FFFFFFF, 50)
   Dim p As Char* = str
   Dim ch As Char = p(0)
   Do While True
       If ((Not Number.IsWhite(ch) OrElse ((options And NumberStyles.AllowLeadingWhite) = NumberStyles.None)) OrElse (((num And 1) <> 0) AndAlso (((num And 1) = 0) OrElse (((num And &H20) = 0) AndAlso (numfmt.numberNegativePattern <> 2))))) Then
           If (flag2 = (((options And NumberStyles.AllowLeadingSign) <> NumberStyles.None) AndAlso ((num And 1) = 0)) AndAlso (Not chPtr2 = Number.MatchChars(p, numfmt.positiveSign) Is Nothing)) Then
               num = (num Or 1)
               p = (chPtr2 - 1)
           ElseIf (flag2 AndAlso (Not chPtr2 = Number.MatchChars(p, numfmt.negativeSign) Is Nothing)) Then
               num = (num Or 1)
               number.sign = True
               p = (chPtr2 - 1)
           ElseIf (((ch = "("c) AndAlso ((options And NumberStyles.AllowParentheses) <> NumberStyles.None)) AndAlso ((num And 1) = 0)) Then
               num = (num Or 3)
               number.sign = True
           Else
               If (((currencySymbol Is Nothing) OrElse (chPtr2 = Number.MatchChars(p, currencySymbol) Is Nothing)) AndAlso ((ansiCurrencySymbol Is Nothing) OrElse (chPtr2 = Number.MatchChars(p, ansiCurrencySymbol) Is Nothing))) Then
                   Exit Do
               End If
               num = (num Or &H20)
               currencySymbol = Nothing
               ansiCurrencySymbol = Nothing
               p = (chPtr2 - 1)
           End If
       End If
       ch = ++p
   Loop
   Dim num3 As Integer = 0
   Dim index As Integer = 0
   Do While True
       If (((ch >= "0"c) AndAlso (ch <= "9"c)) OrElse (((options And NumberStyles.AllowHexSpecifier) <> NumberStyles.None) AndAlso (((ch >= "a"c) AndAlso (ch <= "f"c)) OrElse ((ch >= "A"c) AndAlso (ch <= "F"c))))) Then
           num = (num Or 4)
           If (((ch <> "0"c) OrElse ((num And 8) <> 0)) OrElse flag4) Then
               If (num3 < num2) Then
                   If flag3 Then
                       sb.Append(ch)
                   Else
                       number.digits(num3++) = ch
                   End If
                   If ((ch <> "0"c) OrElse parseDecimal) Then
                       index = num3
                   End If
               End If
               If ((num And &H10) = 0) Then
                   number.scale += 1
               End If
               num = (num Or 8)
           ElseIf ((num And &H10) <> 0) Then
               number.scale -= 1
           End If
       ElseIf ((((options And NumberStyles.AllowDecimalPoint) <> NumberStyles.None) AndAlso ((num And &H10) = 0)) AndAlso ((Not chPtr2 = Number.MatchChars(p, currencyDecimalSeparator) Is Nothing) OrElse ((flag AndAlso ((num And &H20) = 0)) AndAlso (Not chPtr2 = Number.MatchChars(p, numberDecimalSeparator) Is Nothing)))) Then
           num = (num Or &H10)
           p = (chPtr2 - 1)
       Else
           If (((((options And NumberStyles.AllowThousands) = NumberStyles.None) OrElse ((num And 4) = 0)) OrElse ((num And &H10) <> 0)) OrElse ((chPtr2 = Number.MatchChars(p, currencyGroupSeparator) Is Nothing) AndAlso ((Not flag OrElse ((num And &H20) <> 0)) OrElse (chPtr2 = Number.MatchChars(p, numberGroupSeparator) Is Nothing)))) Then
               Exit Do
           End If
           p = (chPtr2 - 1)
       End If
       ch = ++p
   Loop
   Dim flag5 As Boolean = False
   number.precision = index
   If flag3 Then
       sb.Append(ChrW(0))
   Else
       number.digits(index) = ChrW(0)
   End If
   If ((num And 4) <> 0) Then
       If (((ch = "E"c) OrElse (ch = "e"c)) AndAlso ((options And NumberStyles.AllowExponent) <> NumberStyles.None)) Then
           Dim chPtr3 As Char* = p
           ch = ++p
           chPtr2 = Number.MatchChars(p, numfmt.positiveSign)
           If (Not chPtr2 Is Nothing) Then
               ch = p = chPtr2
           Else
               chPtr2 = Number.MatchChars(p, numfmt.negativeSign)
               If (Not chPtr2 Is Nothing) Then
                   ch = p = chPtr2
                   flag5 = True
               End If
           End If
           If ((ch >= "0"c) AndAlso (ch <= "9"c)) Then
               Dim num5 As Integer = 0
               Do
                   num5 = ((num5 * 10) + (ch - "0"c))
                   ch = ++p
                   If (num5 > &H3E8) Then
                       num5 = &H270F
                       Do While ((ch >= "0"c) AndAlso (ch <= "9"c))
                           ch = ++p
                       Loop
                   End If
               Loop While ((ch >= "0"c) AndAlso (ch <= "9"c))
               If flag5 Then
                   num5 = -num5
               End If
               number.scale = (number.scale + num5)
           Else
               p = chPtr3
               ch = p(0)
           End If
       End If
       Do While True
           If (Not Number.IsWhite(ch) OrElse ((options And NumberStyles.AllowTrailingWhite) = NumberStyles.None)) Then
               If (flag2 = (((options And NumberStyles.AllowTrailingSign) <> NumberStyles.None) AndAlso ((num And 1) = 0)) AndAlso (Not chPtr2 = Number.MatchChars(p, numfmt.positiveSign) Is Nothing)) Then
                   num = (num Or 1)
                   p = (chPtr2 - 1)
               ElseIf (flag2 AndAlso (Not chPtr2 = Number.MatchChars(p, numfmt.negativeSign) Is Nothing)) Then
                   num = (num Or 1)
                   number.sign = True
                   p = (chPtr2 - 1)
               ElseIf ((ch = ")"c) AndAlso ((num And 2) <> 0)) Then
                   num = (num And -3)
               Else
                   If (((currencySymbol Is Nothing) OrElse (chPtr2 = Number.MatchChars(p, currencySymbol) Is Nothing)) AndAlso ((ansiCurrencySymbol Is Nothing) OrElse (chPtr2 = Number.MatchChars(p, ansiCurrencySymbol) Is Nothing))) Then
                       Exit Do
                   End If
                   currencySymbol = Nothing
                   ansiCurrencySymbol = Nothing
                   p = (chPtr2 - 1)
               End If
           End If
           ch = ++p
       Loop
       If ((num And 2) = 0) Then
           If ((num And 8) = 0) Then
               If Not parseDecimal Then
                   number.scale = 0
               End If
               If ((num And &H10) = 0) Then
                   number.sign = False
               End If
           End If
           str = p
           Return True
       End If
   End If
   str = p
   Return False
End Function


Espero que se pueda entender la diferencia, y lo que denomino robustez ...aparte de lo que ya he comentado sobre ello.

Doy este debate por finalizado para no desviar todavía más el tema principal.

Saludos!








__Alvaro 2015__

#7
Hola,

Citar
Espero que se pueda entender la diferencia, y lo que denomino robustez ...aparte de lo que ya he comentado sobre ello.

Si es mas robusto, pero también es mucho mas pesado, y gracias a esa metodología de no optimizar mas en en velocidad y ahorro de código, las plataformas Windows se han vuelto toscas, lentas y evidentemente sobrecargadas, por ello Linux gana mas y mas usuarios día a día.

Acordaremos no estar de acuerdo, en todo, así no se hace spam.

Saludos.
"Pasión por la programación"

nevachana

No sé en que lenguaje estás pero es muy sencillo ^^
creas una lista con los caracteres no deseados:
Código (csharp) [Seleccionar]
    public static List<string> blocked = new List<string>
        {
            "a",
            "b",
            "c"
        };

después en el botón donde hagas la acción añades una condicional.
Código (csharp) [Seleccionar]
    if(blocked.Contains(textBox1.Text))
              MessageBox.Show("Caracter no válido");
          else
              MessageBox.Show("Caracter válido");