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
Related
In VB.net, I am sending SCPI commands via GPIB-to-USB to an agilent/keysight device. I am using this sample to write data to instruments. https://www.keysight.com/main/editorial.jspx?cc=BR&lc=por&ckey=492255&nid=-33170.1090751.08&id=492255
Here is a portion of my code that I am having trouble with.
Dim P As Integer
Dim Power As Integer
For P = -50 To 0 Step 10
System.Threading.Thread.Sleep(500)
Power = P
instrument.WriteString("POW" & Str$(P) & "dbm")
Console.WriteLine("Power" & P) 'Testing if this portion of the for loop is reached
My code builds successfully, but the device I am communicating with displays an error message saying "invalid separator." I believe the problem is that P starts as a negative number. If I were to do something like, For P=0 to 10 step 1, it would work on the device receiving the command. However, Str$ does not seem to be work with negative numbers. Using Console.WriteLine, I do see that my loop is working correctly in the console output. Based on the console output, the structure of the loop is not the problem.
How could I make this work with P starting as a negative number? I tested the code and device to see if it can take negative numbers by simply using instrument.WriteString("POW -5 dbm") and that works. I really believe the problem involves Str$. I also tried doing ("POW" & P.ToString() & "dbm") but that did not work either. I also replaced Str$ with CStr but that did not work either. Also note that the sleep/delay is not an issue because I implemented that in another for loop and it worked with no errors.
I just figured it out. There has to be a space after POW. It should look like "POW "
Ok so I was in college and I was talking to my teacher and he said my code isn't good practice. I'm a bit confused as to why so here's the situation. We basically created a for loop however he declared his for loop counter outside of the loop because it's considered good practice (to him) even though we never used the variable later on in the code so to me it looks like a waste of memory. We did more to the code then just use a message box but the idea was to get each character from a string and do something with it. He also used the Mid() function to retrieve the character in the string while I called the variable with the index. Here's an example of how he would write his code:
Dim i As Integer = 0
Dim justastring As String = "test"
For i = 1 To justastring.Length Then
MsgBox( Mid( justastring, i, 1 ) )
End For
And here's an example of how I would write my code:
Dim justastring As String = "test"
For i = 0 To justastring.Length - 1 Then
MsgBox( justastring(i) )
End For
Would anyone be able to provide the advantages and disadvantages of each method and why and whether or not I should continue how I am?
Another approach would be, to just use a For Each on the string.
Like this no index variable is needed.
Dim justastring As String = "test"
For Each c As Char In justastring
MsgBox(c)
Next
I would suggest doing it your way, because you could have variables hanging around consuming(albeit a small amount) of memory, but more importantly, It is better practice to define objects with as little scope as possible. In your teacher's code, the variable i is still accessible when the loop is finished. There are occasions when this is desirable, but normally, if you're only using a variable in a limited amount of code, then you should only declare it within the smallest block that it is needed.
As for your question about the Mid function, individual characters as you know can be access simply by treating the string as an array of characters. After some basic benchmarking, using the Mid function takes a lot longer to process than just accessing the character by the index value. In relatively simple bits of code, this doesn't make much difference, but if you're doing it millions of times in a loop, it makes a huge difference.
There are other factors to consider. Such as code readability and modification of the code, but there are plenty of websites dealing with that sort of thing.
Finally I would suggest changing some compiler options in your visual studio
Option Strict to On
Option Infer to Off
Option Explicit to On
It means writing more code, but the code is safer and you'll make less mistakes. Have a look here for an explanation
In your code, it would mean that you have to write
Dim justastring As String = "test"
For i As Integer = 0 To justastring.Length - 1 Then
MsgBox( justastring(i) )
End For
This way, you know that i is definitely an integer. Consider the following ..
Dim i
Have you any idea what type it is? Me neither.
The compiler doesn't know what so it defines it as an object type which could hold anything. a string, an integer, a list..
Consider this code.
Dim i
Dim x
x = "ab"
For i = x To endcount - 1
t = Mid(s, 999)
Next
The compiler will compile it, but when it is executed you'll get an SystemArgumenException. In this case it's easy to see what is wrong, but often it isn't. And numbers in strings can be a whole new can of worms.
Hope this helps.
I have the following variable declaration in a procedure which works fine.
Dim table_rng As Range
Dim attachments_rng As Range
I did have it as:
Dim table_rng, attachments_rng As Range
but this caused a "Compile error: ByRef argument type mismatch".
Since I have working code I'm not in a crisis but I wasted an hour finding this solution.
I'm using Excel 2010 with Visual Basic for Applications 7.0.1628
As far as I know the second declaration is syntactically correct. Am I missing something? I searched in vain on the web and stackoverflow.com for any wisdom on the topic.
Thanks in advance.
So, please take a look at VBA editor on this. First statement seems like to declare 3 integers, but not. Variable i and j are variant and only k is integer.
So if you look on your code, table_rng is declared as variant/empty and maybe this is what causing issue, but without rest of your code i cant tell you more.
But i recommend you to use single variable declaration on line, its far more easier to read. Or if you wana to declare more variable on single line, you need to specifi date type for each of them (like last line on my example. If you wana to know variable types, use debugging in VBA and View/Locals window).
Sub testVarDeclar()
Dim i, j, k As Integer
Dim a As Integer, b As Integer
Dim table_rng, attachments_rng As Range
Dim table_rng2 As Range, attachments_rng2 As Range
End Sub
I recently installed VS2013 (alongside a previous VS2010 installation) and noticed I no longer receive the compiler warning 'BC42324' (text below) when compiling identical VB.NET code (I recompiled back in VS2010 to confirm warning is still shown):
Using the iteration variable in a query expression may have
unexpected results. Instead, create a local variable within the loop
and assign it the value of the iteration variable.
Documentation on MSDN seems to suggest the warning is still included. I see/don't-see the warning with the following code :
Dim Numbers = {0, 1}
For Each index In Numbers
Dim SumPlusIndex = Aggregate x In Numbers Select x + index Into Sum()
Next
Has this warning genuinely been removed? Is so how come? If not could there be other environmental differences between my VS2010 and VS2013 installation that might cause the difference?
Yes, that's the infamous capture the for loop variable bug. It has bitten many programmers so Microsoft decided to do something about it. They solved it for a For Each loop, but not a For loop. You can still trigger the warning like this:
Sub Main()
For ix As Integer = 1 To 10
Dim dlg = Sub()
Console.WriteLine(ix) '' Eek!
End Sub
'' etc...
Next
End Sub
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).