Why does the following code print out its below value, specifically with regards to the CShort method in VB.Net?
Console.WriteLine(CShort(False)) 'prints 0
Console.WriteLine(CShort(True)) 'prints -1
I have been able to reproduce this with many of the Visual Basic type conversions.
Was this just a design decision in Visual Basic?
In Visual Basic, the Boolean data type is stored as a 16 bit signed integer.
In this representation , -1 evaluates to 16 one bits and 0 is, of course, 16 zero bits.
Hence, if you want the relationship True = Not False to hold, then True must have the value -1.
It's not a VB-specific thing - all VB does is implicitly cast it for you to short.
In C#, you get the same result with an explicit call to a System.Convert method - e.g., System.Convert.ToInt16(true).
Related
I ran in a problem with an inadequate type declaration for the counter variable of a for-next loop.
What´s wrong with this code snippet?
For n As Byte = 16 to 2 Step -1
Debug.Print(n)
Next
-> The loop is never entered,
while the code
For n As SByte = 16 to 2 Step -1
Debug.Print(n)
Next
works as expected.
I´ve been using VB since 1994, currently Visual Studio Community 2019, V16.8.2, but never ran into this problem.
If n needs to be of a "signed" datatype when Step is of type SByte, Integer ..., to handle neg. numbers, why do I not get an Error, Alert ... from the VS-Compiler?
There is also not hint within the MS doc.
Sure this "problem" can be avoided by using (signed)Byte, Integer, double or decimal as datatypes, but I´d like to understand why VS doesn´t give any alert.
Did I miss something?
Regards
Werner
This question already has answers here:
Ternary operator VB vs C#: why resolves Nothing to zero? [duplicate]
(7 answers)
Closed 3 years ago.
I was surprised when I tried to assign null value to a variable using ternary expression in vb.net. When I assign through ternary expression, it doesn't works as expected.
Dim i As Integer? = Nothing
Dim j As Integer? = Nothing
i = If(True, j, 1)
j = If(True, Nothing, 1)
After execution of this code: i is nothing but j becomes 0 (zero). Why?
What is the explanation?
Why I can"t assign directly Nothing (Null) value?
I think the important thing to understand here is Nothing in VB.Net is not the same as null in other languages, because you can still assign Nothing to value types. In many other languages, null is a reference-type construct only. If you're familiar with C#, Nothing is closer to default(T) than to null.
With that in mind, take a fresh look at this expression:
If(True, Nothing, 1)
The compiler evaluates the entire expression on it's own merits, knowing nothing about i or j, even though j is the target of the assignment. The expression has to be able to stand alone.
VB.Net must also determine a type to use for the expression, and it must do this at compile-time. It is not able to infer anything from the use of Nothing about needing an Integer? rather than a basic non-nullable Integer for this type, because VB.Net is perfectly happy to assign Nothing to value types. Therefore the type of the conditional expression can only be inferred from the 1 literal in the final argument, which is a plain Integer, and not Integer?.
Given that resulting type, we now must evaluate Nothing as an integer, where the result is the 0 you observed. In theory, this part is done at runtime rather than compile time, but in practice I suspect the compiler or jitter recognizes the chance to optimize things and rewrites it all down to just j = 0.
If you want to be able to assign an Integer? with a value of Nothing, do it as you did in the first example and keep a variable handy with the correct type you can use for the assignment.
I am not much familiar with Visual Basic 6.0 and am not having a VB compiler installed, but I was looking at some VB code for some debugging and saw this:
Private Function IsFieldDeleted(oLayoutField As Object)
Dim oColl As Collection
Set oColl = GetFieldIdsForField(oLayoutField)
IsFieldDeleted = (oColl.Count = 0)
Set oColl = Nothing
End Function
In other functions I see they define the return type with an "As" for example "As Boolean" but this one does not have an "As" :D and then how they have used it is like this:
If Not IsFieldDeleted(oRptField.GetUCMRLayoutField) Then
Call oCollection.Add(oRptField, oRptField.ObjectKeyString)
Call AddToNewLineSeperatedString(sCaseFldDescMsg, oFld.FieldDescription)
End If
How is this working? Is it just like rewriting it and saying that the function returns an integer and compare the return type to be either 0 or 1? Or are there some other hidden tips in there?
When no type is specified, in VB.NET it assumes Object for the return type. In VB6, it assumes Variant. In VB.NET you can make things much more obvious by turning Option Strict On, but I don't believe that option was available in VB6.
The value that is returned, in reality, is still typed as a Boolean, but you are viewing the returned value as a Variant. So, to do it "properly", you really ought to cast the return value like this:
If Not CBool(IsFieldDeleted(oRptField.GetUCMRLayoutField)) Then
....
End If
Calling CBool casts the value to a Boolean instead of a Variant. This is unnecessary, though, since VB will use late-binding to determine the type of the return value is a boolean.
The best thing to do in this case is to change the function to As Boolean. Doing so will not break any existing code since that's all it ever returned anyway. However, if it's a public member in a DLL, that would break compatibility.
What's the return value when I do an assignment?
For example, can I do this? (i.e. the assignment returns the value being assigned)
Dim a As Integer = 1
Dim b As Integer = 2
a = b = 3
The question came up when I wrote this code today:
Dim updates = GetUpdates()
While updates.Count > 0
Foo.ApplyUpdates(updates)
updates = GetUpdates()
End While
I kind of wish I could have written it this way...
While (updates = GetUpdates).Count > 0
Foo.ApplyUpdates(updates)
End While
I know it's not as clean... (and I totally never declared updates) but it got me curious about how assignments work in .NET... is it a function with a return value? If so... what does it return?
Edit
I gave the first chunk of code a try. It looks like the compiler interprets it as assigning the result of comparing b and 3 to a... which is a compiler error of course.
And for the second code chunk, I get that the operator = is not defined for what ever type updates is... i.e. it thinks it's a comparison, not an assignment.
So to add to my question, why does it work this way? Is it just because vb.net overloads the symbol = with two meanings (assignment and comparison)?
about how assignment working in .NET.
This is actually about how assignment works in VB, not in .NET.
This does not work in VB.Net. The = Operator in VB.Net merely "assigns the value on its right to the variable or property on its left."
What's the return value when I do an assignment?
As seen in the above statement, the assignment operator does not return a value in VB.Net.
Note that this differs from other .NET languages. For example, in C#, the assignment = Operator does what you're describing, and "stores the value of its right-hand operand in the storage location, property, or indexer denoted by its left-hand operand and returns the value as its result."
Dim a As Integer
Dim b As Integer
a = b = 3
Note that, with Option Strict specified, this will actually be an error: "Option Strict On disallows implicit conversions from 'Boolean' to 'Integer'."
This is because VB.Net sees this as two operations - it's basically trying to do:
Dim a As Integer
Dim b As Integer
Dim temp as Boolean
temp = (b = 3)
a = temp
So to add to my question, why does it work this way? Is it just because vb.net overloads the symbol = with two meanings (assignment and comparison)?
Well, it's how the language was designed. I suspect that you are correct, though, and since the same operator (=) is used as an assignment and a comparison is why VB was made this way. However, the original VB language was this way, and to keep the syntax for VB.Net the same (or as close as possible), I suspect this behavior was carried forward.
In Visual Basic a = b = 3 translates to something somewhat unexpected. Since VB doesn't have the == operator and instead uses = for both assignments and equality comparision, the above expression comes down to the following:
If b = 3 Then
a = True
Else
a = False
End If
I had a strange error in a VB6 app this morning and it all stems from the fact that IsNumeric is not working as I expected. Can someone shed some light on why? To me this seems like a bug.
This code displays 4.15877E+62 in a message box:
Dim strMessage As String
strMessage = "0415877D57"
If IsNumeric(strMessage) Then
MsgBox CDbl(strMessage)
Else
MsgBox "not numeric"
End If
I am guessing that the runtime engine is incorrectly thinking that the D is in fact an E?
I think this is a bug though as the exact same code in VB.NET outputs not numeric
Is this a known issue with IsNumeric?
If you check the VB6 docs:
Note Floating-point values can be expressed as mmmEeee or mmmDeee, in which mmm is the mantissa and eee is the exponent (a power of 10). The highest positive value of a Single data type is 3.402823E+38, or 3.4 times 10 to the 38th power; the highest positive value of a Double data type is 1.79769313486232D+308, or about 1.8 times 10 to the 308th power. Using D to separate the mantissa and exponent in a numeric literal causes the value to be treated as a Double data type. Likewise, using E in the same fashion treats the value as a Single data type.
I've been using my own IsNumber function for a long time exactly because of this situation. IsNumeric can also return true for certain money symbols, like this: IsNumeric("$34.20").
My IsNumber function looks like this:
Public Function IsNumber(ByVal Data As String) As Boolean
If Data = "" Then
IsNumber = False
Exit Function
End If
IsNumber = IsNumeric(Data & "e0")
End Function
The idea here is... if there is already an e or d in the data, adding another will cause the data to NOT be numeric using the IsNumeric check. You can easily change this function to only allow for integers by replacing "e0" with ".0e0". Want just positive integers? then use this: IsNumeric("-" & Data & ".0e0")
The only downside of this method is that an empty string normally is not numeric, but when you append "e0" to it, it becomes numeric so you need to add a check for that, like I did in my code.
I suggest making a custom validator. Do you want to allow 0-9 only? What about negatives? Commas? I never cared for Microsoft's implementation, but I understand it.