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?
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:
''' <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:
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).
' ***********************************************************************
' 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.
Puedes utilizar la Función "IsNumeric", ejemplo:
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 ::)
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:
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!
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.
Yo lo solucione de esta manera espero te sirva
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
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)
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:
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:
<__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!
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.
No sé en que lenguaje estás pero es muy sencillo ^^
creas una lista con los caracteres no deseados:
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.
if(blocked.Contains(textBox1.Text))
MessageBox.Show("Caracter no válido");
else
MessageBox.Show("Caracter válido");