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!