For example, I would like to assign &H80000000 to a 64-bit signed integer variable:
Dim a As Long = &H80000000
However, integer a has value &HFFFFFFFF80000000 instead of &H80000000.
I tried to call CULng to circumvent the sign-extension. Nonetheless, it says "Constant expression not representable in type 'ULong'". I conjecture this is because Visual Basic prohibits a negative integer to be assigned to an unsigned variable.
I am using Visual Basic 2010 (.NET Framework 4.0)
Dim a As Long = &H80000000L
Use the literal suffix L to tell the compiler that you intend this value to be a long literal. Otherwise, it's interpreted as a signed integer literal representing a negative value (-2147483648). Alternatively, you can use the suffix UI to denote an unsigned integer.
Example code:
Dim a As Long = &H80000000 ' Int32 literal -2147483648
Dim b As Long = &H80000000L ' Int64 literal 2147483648
Dim c As Long = &H80000000UI ' UInt32 literal 2147483648
Console.WriteLine(a.ToString("X")) ' FFFFFFFF80000000
Console.WriteLine(b.ToString("X")) ' 80000000
Console.WriteLine(c.ToString("X")) ' 80000000
I do not understand at all how to use TryCast in my code, but it is something I need to use for validating user input. I have done various searches and looked at various questions on here, but no one seems to actually say how to use it, and the MSDN website doesn't seem to help at all.
Function ValidateInput(Var_In As String) As Integer
If TryCast(Var_In, Integer) = Nothing Then
Return vbNull
Else
Return Var_In
End If
End Function
The error says that
The operand must be of reference type but Integer is of value type
What is the explanation of what I have done wrong?
TryParse doesn't accept more than 10 digits so for example, an input of "12345678901" won't be accepted. How do I fix this?
Let's try to understand the differences between TryCast, Convert and TryParse.
TryCast
This function will attempt to convert one object into another type, as long as it is a reference type.
Dim MyNewObject = TryCast(MyObject, MyReferenceClass)
If IsNothing(MyNewObject) Then
MessageBox.Show("Impossible to cast")
End If
Since Integer is a value type, it will not work, so we have to figure something out...
Convert
Convert Class on MSDN
From MSDN:
Converts a base data type to another base data type.
So we can try:
Dim myInt = Convert.ToInt32(MyObject)
The problem is that it will generate an exception InvalidCastException if it's impossible to do the conversion.
TryParse
This function is trying to convert a String into something you want. And it will not generate an exception:
Dim myInt As Integer = 0
If Not Integer.TryParse(MyString, myInt) Then
MessageBox.show("This is not an integer")
End If
Limitation
Converting a String into a Integer can sometimes be tricky... If the String represents a number that is greater or lesser than Integer.MaxValue and Integer.MinValue, you will end up with no conversion...
So you can go with a Double:
Double.TryParse(MyString, MyDouble)
Or personally, if you know that it will be a number, use Decimal:
Decimal.TryParse(MyString, MyDecimal)
See Decimals on MSDN
Decimal still has a Max and Min value, according to MSDN:
The Decimal value type represents decimal numbers ranging from positive 79,228,162,514,264,337,593,543,950,335 to negative 79,228,162,514,264,337,593,543,950,335. The Decimal value type is appropriate for financial calculations that require large numbers of significant integral and fractional digits and no round-off errors.
Convert.ChangeType
This one is also interesting, but is a bit weird...
You are attempting to perform TryCast against an Integer, which is a value type. TryCast works only on reference types, such as (but not limited to) a Class, Object, or String type.
If you are trying to convert the input parameter to an Integer, you might try one of the methods in the Convert class, such as Convert.ToInt32() or Integer.TryParse.
Instead of TryCast, use TryParse:
Function ValidateInput(Var_In As String) As Integer
Dim iNum As Integer
If (Integer.TryParse(Var_In, iNum)) Then
Return iNum
Else
Return vbNull
End If
End Function
Much better is to use TryParse:
Function ValidateInput(Var_In As String) As Integer
Dim num as Integer
If Not Integer.TryParse(Var_In, num) Then
Return vbNull
Else
Return num
End If
End Function
I'm late to the discussion, but if anyone lands here (like I did) looking for a quick & dirty solution, here a function I'm using for simple cell validation in a DataGridView control.
Function TryTypeFit(theString As String, theType As Type, ShowError As Boolean) As Boolean
Dim TempReturn As Boolean = False
Dim TempObject As Object
Try
TempObject = Convert.ChangeType(theString, theType)
TempReturn = True
Catch ex As Exception
' didn't work
TempReturn = False
If ShowError Then
Dim eMessage As String = "Error: Value must be castable to a " & CStr(theType.Name)
MsgBox(eMessage)
End If
End Try
100:
Return TempReturn
End Function
I am converting a VB6 application to VB.net. The application uses an existing C library I can't change.
The Problem: I am expecting a value around -180 or 180. The times that I expect 180, it works. But when I expect -180, I get the value 4294967117. This seems like the C library is returning a 2's complement number, but I don't know how to treat it.
This is the VB6 code that works:
Dim tmp As Long
If GetVal(VAL_A1, tmp) = ERR_VAL_NA Then
lblAngle(0).Caption = "na"
Else
lblAngle(0).Caption = tmp
End If
This is the VB.net code that does not work:
If GetVal(VAL_A1, tmp) = ERR_VAL_NA Then
txtBoxPhaseAngle1.Text = "na"
Else
txtBoxPhaseAngle1.Text = Convert.ToDouble(tmp)
End If
I have also tried:
txtBoxPhaseAngle1.Text = Convert.ToInt32(tmp)
txtBoxPhaseAngle1.Text = tmp
EDIT :
How I declare the C function:
Declare Function GetVal Lib "Z:\Devel\RelayAPI\Debug\RelayAPI.dll" (ByVal what As
Integer, ByRef val As Long) As Byte
Snippets from the GetVal function in the C code:
BYTE __stdcall GetVal(WORD what, long *val){
DWORD relaydate;
BYTE tmpb;
DWORD tmpd;
long tmp;
...
switch(what){
case VAL_A1:
tmpb=RelayAPI_Scaled;
if(tmpd<6){
*val=(short)((WORD)mon[38]+((WORD)mon[39]<<8));
}else{
*val=(short)((WORD)mon[32]+((WORD)mon[33]<<8));
}
break;
break;
}
When upgrading from VB6, you need to be aware that some data types have changed. In VB6, an Integer is 16-bits, and a Long is 32-bits. In VB.NET, though, an Integer is 32-bits and a Long is 64-bits.
In the C function, you have long *val, and a C long is "at least 32-bits" according to spec, so presumably your C-function is returning a 32-bit integer. However, VB.NET now believes that it's a Long (64-bit) value, and interprets it as such -- 4294967117 instead of -180.
If you change your VB.NET declaration of the val parameter to ByRef val As Integer, you will probably see the correct return value.
I have a timer which returns the time elapsed:
Public Function TimeElapsed() As ULong
Dim ul As ULong
ul = m_lEnd - m_lStart
Dim ul2 As ULong
ul2 = ul - m_lOverhead
Dim ul3 As ULong
ul3 = (ul2 / m_lFreq) * 1000
Return ul3
End Function
Now I experienced the following variables:
m_lEnd = 935083366402
m_lStart = 935007142800
ul2 = 76223588
m_lOverhead = 14
This gives me an overflow in the line
ul3 = (ul2 / m_lFreq) * 1000
I can not see why and how to improve my bug.
Thank you very much for the help!
You need to explicitly tell the compiler you are doing the operation on a ULong... This is because the numeric literals default to Integers, so your trying to use an integer literal which will cause an overflow like your issue. You can force values to different types with the correct suffix. Literal values without a type suffix may only have values up to the range of Long. This case it's ULong so the suffix is: UL.
By the way this is a conversion error, turn Option Strict on...
EX: Dim m_lEnd As ULong = 935083366402UL
Notice this at the end, this is what needs to happen.
I'm using a library call, setInstance(ByVal instance As UInteger), in my VB.NET code. The parameter I need to pass is an Integer. Is there anything I need to do to convert the integer parameter to an unsigned integer? The number is guaranteed to be positive and less than 10.
Like so...
Dim MyInt As Int32 = 10
Dim MyUInt As UInt32 = CUInt(MyInt)
setInstance(MyUInt)
CUInt or CType(x, UInt) allow converting a positive integer.
It throws an exception when x is negative.
To use Int as Uint, you can use some tricks:
dim bb() = System.BitConverter.GetBytes(myInt)
dim MyUint = System.BitConverter.ToUInt32(bb, 0)
Also with System.Buffer.BlockCopy for arrays.
If you configure the compiler to disable Check Integer Overflow (default for C#). Then you can use CUInt with negative values with no check - not exception.
You can call CUint to convert a variable to a UInteger.