Why not to use a 'Return' statement in VB.NET? - vb.net

I've been given some code to go through and find problems and things that could be improved and changed (it's a homework task, but this question is unrelated to the task itself), part of the code is:
Function CheckIfSameCell(ByVal FirstCellPosition As CellReference, ByVal SecondCellPosition As CellReference) As Boolean
Dim InSameCell As Boolean
InSameCell = False
If FirstCellPosition.NoOfCellsSouth = SecondCellPosition.NoOfCellsSouth And FirstCellPosition.NoOfCellsEast = SecondCellPosition.NoOfCellsEast Then
InSameCell = True
End If
CheckIfSameCell = InSameCell
End Function
I can't understand why the InSameCell is variable is created, when it can just be assigned to the function name CheckIfSameCell?
Or just use return statements as in the following?
Function CheckIfSameCell(ByVal FirstCellPosition As CellReference, ByVal SecondCellPosition As CellReference) As Boolean
If FirstCellPosition.NoOfCellsSouth = SecondCellPosition.NoOfCellsSouth And FirstCellPosition.NoOfCellsEast = SecondCellPosition.NoOfCellsEast Then
Return True
End If
Return False
End Function
I can understand not returning the expression in the If statement directly, to increase readability.
I know that assigning a return value to the Function name doesn't exit the function, whereas Return does, but is it just a person's style, or is there any advantage to the first version (IMO, the second is more readable)?

Maybe there used to be more checks, where value of InSameCell could change several times and only then get returned. Using return then would change behaviour.
Maybe the author wanted to avoid the tedious renaiming. You know, when you want to rename a function, and you use that function's name many times within its own body, then you have many places to replace, whereas when you introduce a variable you will only have one place to change the name in. (I know the IDE will properly do that for you; but that was not the case in VB6, and habits are difficult to break.)
Maybe the author was much more familiar with VB6 that didn't have return.
Maybe it was a matter of style or policy.
Anyway, I would write it as:
Function CheckIfSameCell(ByVal FirstCellPosition As CellReference, ByVal SecondCellPosition As CellReference) As Boolean
Return FirstCellPosition.NoOfCellsSouth = SecondCellPosition.NoOfCellsSouth AndAlso FirstCellPosition.NoOfCellsEast = SecondCellPosition.NoOfCellsEast
End Function

Assigning the result to the function name is an old style used in VB6 and should not be used any more in VB.NET. Use Return value!
Personally I dislike statements in the style
If condition Then
Return True
Else
Return False
End If
They are just stupid, since condition already yields the return value! Better:
Return condition
It is also the solution chosen by GSerg.
Nobody would write
If x + y = 0 Then
Return 0
ElseIf x + y = 1 Then
Return 1
ElseIf x + y = 2 Then
Return 2
ElseIf x + y = 3 Then
Return 3
...
But some people are constantly doing it when the expression is of type Boolean. I think that they do not realize that conditions are equivalent to arithmetical expressions. They are just arithmetic with Booleans instead of arithmetic with numbers.
Another misconception is that an If-statement requires some comparison like If x > 0 Then. If they have a Boolean variable b they write If b = True Then. But all the If-statement needs is a Boolean value given by a Boolean expression. This expression can be as simple as querying a variable: If b Then.
Why does this work? Because if b is True then b = True yields True and if b is False then b = True yields False. So, b = True is very much like saying x * 1. Of course, this is the same as just x.

The second method is more readable, I concur. It also happens to be my preference for returning out of methods. I really cannot think of a single downside to the latter in comparision, but can for the former. What happens if the method gets longer and someone forgets to set a Boolean flag? A subtle bug would be born. Additionally, it takes more code to write as well. In the latter approach, the code won't compile if it is missing a return, and it also will be shorter.
The only time you need local variables for the return type is when the routine needs to do some other work after the return value is first determined. In the example you post, this is not the case.
Code Complete, 2nd Edition agrees on page 391:
Use a return when it enhances readability In certain routines, once
you know the answer, you want to return it to the calling routine
immediately. If the routine is defined in such a way that it doesn’t
require any further cleanup once it detects an error, not returning
immediately means that you have to write more code.
NOTE: As other answers [1,2] have mentioned, you can reduce the method to a single code statement. Also using AndAlso should help speed up the evaluation by short-circuiting the logical expression early if the first part is false:
Return FirstCellPosition.NoOfCellsSouth = SecondCellPosition.NoOfCellsSouth
AndAlso FirstCellPosition.NoOfCellsEast = SecondCellPosition.NoOfCellsEast

There is one important thing with return and assigning value the the function name. If you (for whatever twisted reason) would like to write something like that
Public Function TestFunct() as Boolean
Dim testVar as Boolean = True
If testVar then
TestFunct = True
Else
TestFunct = False
EndIf
'do more stuff here
...
TestFunct = False
End Function
It will always return false. If you use returns instead it the execution will stop and the function will return correct value.

You might use a variable if for some reason it needs to appear on the right-hand side of an assignment, and you don't want to cause a recursion:
Dim Function F() As Boolean
F = True
If a = b Then
F = Not F()
End If
End Function

In short - Yes your last example is quite valid.
However, most examples used in homework are either used to show other teaching examples. The code in the homework sheet merely shows the basics of using functions in the traditional way and your 2nd example shows the next learning step and is the most compact way of achieving the desired result.
Also, the 1st example could also be used to re-enforce lessons learned earlier - e.g. about assigning variables, use of booleans etc.
One of the best ways to improve your coding skills is to repeatedly practice what you have learned.

Related

Why does VB convert true into -1 not 1? [duplicate]

I am working with some VB.NET code that seems to be casting a boolean value to an integer using CInt(myBoolean). The odd thing that is happening is that it returns -1 if the value is true. For example:
CInt(True) // returns -1
CInt(False) // returns 0
Is this common in other languages?
I thought that a boolean would be 1 if true and 0 if false. Also, is there a way to make Visual Basic assign 1 to true instead of assigning -1?
Typically, a value of false is represented by 0 and a value of true is represented by any non-0 integer value. The specific value for true and false (among others) are things that you shouldn't rely on - they can potentially be implementation specific. I'm not sure what you are trying to do, but it would probably be best to not rely on True or False having any specific integer values unless you absolutely have to.
The best explanation that I could find for VB's specific behavior comes from Wikipedia:
Boolean constant True has numeric value −1. This is because the Boolean data type is stored as a 16-bit signed integer. In this construct −1 evaluates to 16 binary 1s (the Boolean value True), and 0 as 16 0s (the Boolean value False). This is apparent when performing a Not operation on a 16 bit signed integer value 0 which will return the integer value −1, in other words True = Not False. This inherent functionality becomes especially useful when performing logical operations on the individual bits of an integer such as And, Or, Xor and Not.[4] This definition of True is also consistent with BASIC since the early 1970s Microsoft BASIC implementation and is also related to the characteristics of CPU instructions at the time.
A work around for your initial use would be :
Dim i As Integer = CInt(Int(False))
This will return a 0.
Dim i As Integer = CInt(Int(True))
This will return a 1.
It seems like a gotcha, and I don't know any other examples of this behaviour.
Troubleshooting Data Types (Visual Basic) specifies this behaviour, with a "Don't do that, mkay" sorta remark with it. Do note further down:
Conversion in the Framework
The ToInt32 method of the Convert class in the System namespace converts True to +1.
If you must convert a Boolean value to a numeric data type, be careful about which conversion method you use.
I had the same problem and used Math.Abs function on the result :)
The MSDN documentation provides some valuable insight, "Boolean values are not stored as numbers, and the stored values are not intended to be equivalent to numbers. You should never write code that relies on equivalent numeric values for True and False. Whenever possible, you should restrict usage of Boolean variables to the logical values for which they are designed."
Many versions of BASIC in the 1970's and 1980's implemented bit-wise arithmetic with their AND and OR operators, and made true conditional expressions evaluate to -1 (i.e. the "all-bits-set" value in the two's complement used for integers). I'm not sure exactly why the decision was made to have true conditional expressions evaluate to an all-bits-set value; being able to use AND to mask an integer against a conditional expression may have been faster than multiplying, but given then internal mechanics of the interpreters the difference would have been slight.
In any case, the first versions of BASIC that Microsoft produced for the PC followed in that tradition of having true conditionals evaluate to -1 (all-bits-set); since QuickBASIC was in turn supposed to be compatible with those, and Visual Basic was supposed to be compatible with QuickBASIC, they used the same representation. Although .Net recognizes integers and Booleans as different types, VB.Net wanted to offer a migration path for VB6 programs that might rely on the old behavior. With "Option Strict Off", VB.Net will implicitly convert a Boolean value of True to an integer -1; while most programmers use Option Strict On, it would be confusing to have the behavior of CInt() differ from the implicit conversion behavior.
I tested it and got the following results:
Public Module BooleanTest
Public Function GetTrue() As Boolean
GetTrue = True
End Function
End Module
...
[StructLayout(LayoutKind.Explicit)]
struct MyStruct
{
[FieldOffset(0)]
public bool MyBool;
[FieldOffset(0)]
public int MyInt32;
}
static void Main(string[] args)
{
MyStruct b1, b2;
b1.MyInt32 = 0;
b2.MyInt32 = 0;
b1.MyBool = BooleanTest.BooleanTest.GetTrue();
b2.MyBool = true;
Console.WriteLine(b1.MyInt32);
Console.WriteLine(b2.MyInt32);
}
This will result in:
1
1
I hope this proves that all True values inside .NET are always the same. The reason is simple: All .NET members have to communicatie with each other. It would be weird if object.Equals(trueFromCSharp, trueFromVB) would result in false (as will trueFromCSharp == trueFromVB).
CInt is just a function which will convert True into -1. Another function Int will return 1. But these are converters, and do not say anything about the binary values.
I have been having the same problem with MySQL as this has no Boolean type only a tinyint(1).
My solution was to write a converter function to ensure that the values are correct before inserting them into the database
Public Function BoolToMySql(bVal As Boolean) As Integer
Dim retVal As Integer
If bVal = True Then
retVal = 1
Else
retVal = 0
End If
BoolToMySql = retVal
End Function
I hope that is can help others work with Booleans inside VB.NET.
Just as a better way to write the VB.NET that Roger wrote:
Public Function BoolToMySql(bVal As Boolean) As Integer
return If(bVal, 1, 0)
End Function
I found the other answers lacking for the specific VBA scenario I was working with. This is not tested in VB.NET.
I wanted to take any given number that was <> 0 and make it 1, and keep 0 as 0 in a single line of code, without an If statement. The way that I ended up doing this, which I did not see in other given answers, was:
Abs(CBool(iCount))
CBool() converts the given number (iCount in example above) to Boolean, narrowing the possible results to two values; True with a value of -1 and False with a value of 0.
Abs() then takes the absolute value (no negatives) of the Boolean to return 0 for False and 1 for True.
In practice, the following return 0:
Abs(CBool(0))
Abs(False)
And the following return 1:
Abs(CBool(1))
Abs(CBool(-1))
Abs(CBool(-38473))
Abs(CBool(358677))
Abs(True)
I hope that this is useful for anyone else playing with specific scenarios such as this.
I may be a bit late but here's a simple workaround to receive the typical 1 for True and 0 for False.
Multiply the boolean with -1 like so:
CInt(True) * -1
CInt(False) * -1
Which then returns
1
0

Logic operator syntax in VB for my School Project

so I'm writing a Blackjack game for my Advanced Higher Computing Science project at school, and I have a question about the syntax of the logical operators in VB.
Here's the situation..
If X>Y AND (A=True Or B=True Or C=True) Then
Do something
End IF
Let's say for instance that X is indeed greater than Y, and A is true, but B and C are false. As I understand it the statement will execute, because X is greater than Y, AND at least one of the conditions within the brackets is true, but I'm not entirely sure if this is correct. Can the brackets be used this way for things to be logically correct? Or do I have to write conditions regarding A, B and C separately? For example...
If X>Y AND A=True Then
Do something
End IF
If X>Y AND B=True Then
Do something
End IF
If X>Y AND C=True Then
Do something
End IF
Basically, can the brackets be used as a 'short hand' method to make the code slightly shorter and less cluttered? I'm using the latest version of VB, 2015.
Thanks a lot for any help, I appreciate it!
P.S. - I can't put my actual code on the internet, as this could get me in trouble with my exam board as this is an official assessment.
Consider this original example
If X>Y AND (A=True Or B=True Or C=True) Then
It says, that 2 conditions must be met to evaluate this to True. X must be more than Y and also, condition in parenthesis must evaluate to True. First, lets optimize your code to use .net efficiently
If X>Y AndAlso (A OrElse B OrElse C) Then
In your case, if X>Y evaluates to False there is no reason to continue. Hence, AndAlso. This is a shortcut. Same with OrElse. If A evaluates to true, we don't need to evaluate other conditions - this is supported by your logic. Now, A=True - this is noise. And this is why you name Boolean variables, isSomething, hasSomething, [doneSomething], where doneSomething is a verb, i.e. created, completed, disposed, allowed.
Now, lets look at your second piece of code. Obviously what comes into view first, is that you re-evaluating X>Y 3 times and along, you may do Do something 3 times. This syntax widely used but it would be something along these lines (to create same logic as first evaluation)
If Not X>Y Then
Return ' exit because your first evaluation must be true
End If
If A Then
' Do something
Return ' Success and return
End If
If B Then
' Do something
Return ' Success and return
End If
If C Then
' Do something
Return ' Success and return
End If
Of course, the code above makes little sense because there is obvious repetition. This is better
If Not X>Y Then
Return ' exit because your first evaluation must be true
End If
If A OrElse B OrElse C Then
' Do something
End If
This makes more sense but then again, go to line #2 and use optimized single line code - it will do same.

When does = perform comparison instead of assignment?

In VB.NET, there's no == operator for comparison, so the = operator serves that purpose as well as assignment. I have a function, and I want it to return the boolean result of a comparison, without storing that result in a variable:
Private Function foo() As Boolean
Dim bar As Integer = 1
Return bar = 2
End Function
Returns: False
OK, but what's the value of bar?
Private Function foo() As KeyValuePair(Of Boolean, Integer)
Dim bar As Integer = 1
Return New KeyValuePair(Of Boolean, Integer)(bar = 2, bar)
End Function
Returns: False, 1
It looks like = will perform a comparison when the statement context demands it, but is this guaranteed? That is, can I be sure that bar will never be set to 2 in this situation?
Also, I know that VB.NET doesn't allow chained inline assignments, which may be for the best. Does this odd = behavior cause any other quirks I should be aware of?
You cannot do in-line assignments in VB, Assignment is an explicit statement:
[Let] <<target-reference>> = <<value-expression>>
The Let is optional and implicit, and hardly ever used anymore. The general rule that you can use to distinguish the [Let] command from equality testing is that for Let, no other keyword may come before the target-reference in the statement. AFAIK, in all cases of = as equality testing, there is one or more other keywords that precede it in the statement.
In your first example, the keyword Return precedes your =, so it's an equality test, and not an assignment.
In your first example you can do either:
Return 2
or
bar = 2
Return bar
As for your question "OK, but what's the value of bar?", bar still equals one.
= in VB cause no quirks. It works exactly as documented, and it always has (including its predecessor, BASIC back to 1968).
If you are starting to code in VB (coming from a language like C#), you should start getting used to the peculiar VB way of doing things; which is based on the idea: as simple and intuitive for the programmer as possible. "If assignation and comparison happen always in different contexts, why not using the same operator and let the context define its exact meaning?" -> VB-way of seeing things. "No, different realities have to be accounted for by different operators. End of the discussion" -> C#-way. :)
Is this reliable? Can you blindly trust on these not-always-clear-for-a-programmer bits? Sure, VB.NET peculiarities are highly-reliable and trustworthy. You can always use = (or Is on some contexts, but VS would tell you) and be completely sure that the code will do what is expected. But the question is: are you sure that you write exactly what you want?
This last question is what, perhaps, is more criticable of VB and what might give some problems to programmers from other languages: the higher the flexibility, the more likely is that you make an error; mainly if you are used to a different format.
Regarding the chained inline assignments, I honestly don't see its true utility (and never use them in C#). Regarding other differences with respect to C#, there are plenty of them; in some cases, I think that the C# approach is better; other times, the VB.NET one. On readability/length of code, I can refer to the With Statement I have always found somehow useful which is not present in C#.
One way to have 100% sure that the expression will be evaluated as an boolean expression is to use ()
e.g
Dim a = 2
Return (a = 1)
Since you cannot set a value to a variable wihtin the parenthesis.
What i want to say is: on an return statament for example you cant assing a value to a variable so, even if you use
a = 1
The compilator knows that this expression only can be an boolean expression.
The same to the if statament and so on..
Heh back in QB45 days we used to exploit the fact that "True" was the numeric value -1. So you would see code like x = 1 - x * (x < 6) (translation: increment x, but reset to 1 when it gets to 6)

Not keyword vs = False when checking for false boolean condition

When I'm using an If statement and I want to check if a boolean is false should I use the "Not" keyword or just = false, like so
If (Not myboolean) then
vs
If (myboolean = False) then
Which is better practice and more readable?
Definitely, use "Not". And for the alternately, use "If (myboolean)" instead of "If (myboolean = true)"
The works best if you give the boolean a readable name:
if (node.HasChildren)
Since there's no functional difference between either style, this is one of those things that just comes down to personal preference.
If you're working on a codebase where a standard has already been set, then stick to that.
Use True and False to set variables, not to test them. This improves readability as described in the other answers, but it also improves portability, particularly when best practices aren't followed.
Some languages allow you to interchange bool and integer types. Consider the contrived example:
int differentInts(int i, int j)
{
return i-j; // Returns non-zero (true) if ints are different.
}
. . .
if (differentInts(4, 8) == TRUE)
printf("Four and Eight are different!\n");
else
printf("Four and Eight are equal!\n");
Horrible style, but I've seen worse sneak into production. On other people's watches, of course. :-)
Additionally to the consensus, when there is both a true case and a false case please use
if (condition)
// true case
else
// false case
rather than
if (not condition)
// false case
else
// true case
(But then I am never sure if python's x is not None is the true-case or the false case.)
Definitely use "Not", consider reading it aloud.
If you read aloud:
If X is false Then Do Y
Do Y
Versus
If Not X Then Do Y
I think you'll find the "Not" route is more natural. Especially if you pick good variable names or functions.
Code Complete has some good rules on variable names. http://cc2e.com/Page.aspx?hid=225 (login is probably required)
! condition
In C and pre-STL C++, "!condition" means condition evaluates to a false truth value, whereas "condition == FALSE" meant that the value of condition had to equal what the system designed as FALSE. Since different implementations defined it in different ways, it was deemed better practice to use !condition.
UPDATE: As pointed out in the comment -- FALSE is always 0, it's TRUE that can be dangerous.
Something else: Omit the parentheses, they’re redundant in VB and as such, constitute syntactic garbage.
Also, I'm slightly bothered by how many people argue by giving technical examples in other languages that simply do not apply in VB. In VB, the only reasons to use If Not x instead of If x = False is readability and logic. Not that you’d need other reasons.
Completely different reasons apply in C(++), true. Even more true due to the existence of frameworks that really handle this differently. But misleading in the context of VB!
It does not make any difference as long you are dealing with VB only, however if you happen to use C functions such as the Win32 API, definitely do not use "NOT" just "==False" when testing for false, but when testing for true do not use "==True" instead use "if(function())".
The reason for that is the difference between C and VB in how boolean is defined.
In C true == 1 while in VB true == -1 (therefore you should not compare the output of a C function to true, as you are trying to compare -1 to 1)
Not in Vb is a bitwise NOT (equal to C's ~ operator not the ! operator), and thus it negates each bit, and as a result negating 1 (true in C) will result in a non zero value which is true, NOT only works on VB true which is -1 (which in bit format is all one's according to the two's complement rule [111111111]) and negating all bits [0000000000] equals zero.
For a better understanding see my answer on Is there a VB.net equivalent for C#'s ! operator?
Made a difference with these lines in vb 2010/12
With the top line, Option Strict had to be turned off.
If InStr(strLine, "=") = False Then _
If Not CBool(InStr(strLine, "=")) Then
Thanks for answering the question for me. (I'm learning)

Performance difference between IIf() and If

In Visual Basic, is there a performance difference when using the IIf function instead of the If statement?
VB has the following If statement which the question refers to, I think:
' Usage 1
Dim result = If(a > 5, "World", "Hello")
' Usage 2
Dim foo = If(result, "Alternative")
The first is basically C#'s ternary conditional operator and the second is its coalesce operator (return result unless it’s Nothing, in which case return "Alternative"). If has thus replaced IIf and the latter is obsolete.
Like in C#, VB's conditional If operator short-circuits, so you can now safely write the following, which is not possible using the IIf function:
Dim len = If(text Is Nothing, 0, text.Length)
IIf() runs both the true and false code. For simple things like numeric assignment, this isn't a big deal. But for code that requires any sort of processing, you're wasting cycles running the condition that doesn't match, and possibly causing side effects.
Code illustration:
Module Module1
Sub Main()
Dim test As Boolean = False
Dim result As String = IIf(test, Foo(), Bar())
End Sub
Public Function Foo() As String
Console.WriteLine("Foo!")
Return "Foo"
End Function
Public Function Bar() As String
Console.WriteLine("Bar!")
Return "Bar"
End Function
End Module
Outputs:
Foo!
Bar!
Also, another big issue with the IIf is that it will actually call any functions that are in the arguments [1], so if you have a situation like the following:
string results = IIf(Not oraData.IsDBNull(ndx), oraData.GetString(ndx), string.Empty)
It will actually throw an exception, which is not how most people think the function works the first time that they see it. This can also lead to some very hard to fix bugs in an application as well.
[1] IIf Function - http://msdn.microsoft.com/en-us/library/27ydhh0d(VS.71).aspx
According to this guy, IIf can take up to 6x as long as If/Then. YMMV.
Better use If instead of IIf to use the type inference mechanism correctly (Option Infer On)
In this example, Keywords is recognized as a string when I use If :
Dim Keywords = If(String.IsNullOrEmpty(SelectedKeywords), "N/A", SelectedKeywords)
Otherwise, it is recognized as an Object :
Dim Keywords = IIf(String.IsNullOrEmpty(SelectedKeywords), "N/A", SelectedKeywords)
On top of that, readability should probably be more highly preferred than performance in this case. Even if IIF was more efficient, it's just plain less readable to the target audience (I assume if you're working in Visual Basic, you want other programmers to be able to read your code easily, which is VB's biggest boon... and which is lost with concepts like IIF in my opinion).
Also, "IIF is a function, versus IF being part of the languages' syntax"... which implies to me that, indeed, If would be faster... if for nothing else than that the If statement can be boiled down directly to a small set of opcodes rather than having to go to another space in memory to perform the logic found in said function. It's a trite difference, perhaps, but worth noting.
I believe that the main difference between If and IIf is:
If(test [boolean], statement1, statement2)
it means that according to the test value either satement1 or statement2 will executed
(just one statement will execute)
Dim obj = IIF(test [boolean] , statement1, statement2)
it means that the both statements will execute but according to test value one of them will return a value to (obj).
so if one of the statements will throw an exception it will throw it in (IIf) anyway but in (If) it will throw it just in case the condition will return its value.
...as to why it can take as long as 6x, quoth the wiki:
Because IIf is a library function, it
will always require the overhead of a
function call, whereas a conditional
operator will more likely produce
inline code.
Essentially IIf is the equivalent of a ternary operator in C++/C#, so it gives you some nice 1 line if/else type statements if you'd like it to. You can also give it a function to evaluate if you desire.
Those functions are different! Perhaps you only need to use IF statement.
IIF will always be slower, because it will do both functions plus it will do standard IF statement.
If you are wondering why there is IIF function, maybe this will be explanation:
Sub main()
counter = 0
bln = True
s = iif(bln, f1, f2)
End Sub
Function f1 As String
counter = counter + 1
Return "YES"
End Function
Function f2 As String
counter = counter + 1
Return "NO"
End Function
So the counter will be 2 after this, but s will be "YES" only. I know this counter stuff is useless, but sometimes there are functions that you will need both to run, doesn't matter if IF is true or false, and just assign value from one of them to your variable.