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

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

Related

IsNumeric() allowing minus at last of the values

I am using IsNumeric() function in my code to validate numbers.
IsNumeric(100) - true,
IsNumeric(-100) - true,
IsNumeric(+100) - true,
IsNumeric(100-) - true - I have doubt in this. (100-) Is this a valid number? IsNumeric () returns true to this value.
Dim latitude As String = "12.56346-"
If IsNumeric(latitude) Then
If (Convert.ToDouble(latitude) >= -90 And Convert.ToDouble(latitude) <= 90) Then
isValidLatitude.Text = "true"
Else
isValidLatitude.Text = "false"
End If
Else
isValidLatitude.Text = "false"
End If
Error while converting latitude to double
Input string was not in a correct format.
IsNumeric is from the Microsoft.VisualBasic namespace/dll, a bunch of helper stuff intended to help VB6 programmers get their arcane VB6 code /knowledge working on VB.NET
You'll note if you use other functions from the same dll such as Microsoft.VisualBasic.Conversion.Int(), or you use dedicated VB.NET converters such as CInt or CDbl these will also cope with a trailing minus sign and return a negative value
If you want to dispense with the old ways of VB6, use a numeric type's TryParse.. but all in, be consistent / if you use a function from Microsoft.VisualBasic to determine if a conversion can be made, use the vb conversion because within itself the package will be consistent but between Microsoft.VB and normal .net System there are some differences in behavior
Edit:
A couple of people have been wondering about the source code and how it uses TryParse, so why doesn't it work like using TryParse directly?
Microsoft.VisualBasic.Information.IsNumeric() uses Microsoft.VisualBasic.CompilerServices.DoubleType.TryParse() to determine whether an expression is numeric. This DoubleType.TryParse is not the same as Double.TryParse - it is a helper method again in the VB namespace that specifically sets the NumberStyles.AllowTrailingSign flag among many other flags. When parsing the number (first as non currency related, using Double.Parse, then if it fails a second attempt is made using adjusted values for currency related tests) this AllowTrailingSign flag will be considered in conjunction with other regional number formatting rules in determining if the passed in value is numeric
You'll note that on a machine obeying a USA number formatting culture, a string of "(100$)" is also declared to be numeric but calling Double.TryParse("(100$)", x) will also return false. The VB helper methods here are being a lot more liberal in what they accept than the System methods, because they're telling the System methods to be more liberal than they are by default
As noted, I've always regarded the Microsoft.VisualBasic namespace as a bunch of helper methods intended to allow terrible old VB6 code to be pasted into VB.NET and work with minimal fiddling. I wouldn't advocate using it for new projects and I remove the reference when I work on VB.NET - using it to support the VB6 notions of "just sling anything in, of any type, and it'll probably figure it out and work.. and if it doesn't we can always on error resume next" should be discarded in favour of precise and accurate about the operations executed and their intent
Note: my previous answers were wrong about assuming it was a bug. As the answer of #Damien_The_Unbeliever states, this function tries to validate the string as a lot of data types. And actually, the value "100-" is a valid Decimal number. That's why it returns true (as it's a "valid" Decimal) but gives a exception when converting to Double (as it's not a valid Double). #Damien_The_Unbeliever really deserves your +1 for pointing that.
From the documentation (showing all the data types that IsNumeric tries to validate):
IsNumeric returns True if the data type of Expression is Boolean, Byte, Decimal, Double, Integer, Long, SByte, Short, Single, UInteger, ULong, or UShort. It also returns True if Expression is a Char, String, or Object that can be successfully converted to a number. Expression can contain non-numeric characters. IsNumeric returns True if Expression is a string that contains a valid hexadecimal or octal number. IsNumeric also returns True if Expression contains a valid numeric expression that begins with a + or - character or contains commas.
Also, #CaiusJard did a nice search and pointed out that inner methods use a NumberStyles.AllowTrailingSign option, which allows this behavior.
Ok, now to the solution:
Just use a TryParse method, from your desired data type (int, long, etc...). The cool thing is that it'll behaves exactly as you expect, and if the parsing is successful, we have the parsed value already available to use!
if (Int32.TryParse(value, out int number))
{
// String is a valid number, and is already parsed in the 'number' variable!
}
else
{
// String is not a valid number!
}
Solution's VB.Net version:
Dim value As String = "12.56346-"
Dim number As Double = 0
If Double.TryParse(value, number) Then
' String is a valid number, and is already parsed in the "number" variable!
isValidLatitude.Text = "true"
Else
' String is not a valid number!
isValidLatitude.Text = "false"
End If
IsNumeric answers a question no sane person wants to ask. As quoted by Vitox's answer:
IsNumeric returns True if the data type of Expression is Boolean, Byte, Decimal, Double, Integer, Long, SByte, Short, Single, UInteger, ULong, or UShort. It also returns True if Expression is a Char, String, or Object that can be successfully converted to a number.
Note, it doesn't tell you that the given string can be converted to all numeric types. It tells you that the string can be converted to at least one numeric type. And for bonus bad style points, of course, it doesn't tell you which types the string can be converted to.
Decimal.Parse("100-") will execute perfectly well and give you a Decimal containing a value of -100.
So, it's not a bug, it's a bad function that has been retained for backwards compatibility reasons. Nowadays, we know better, and that we want to test whether a string can be converted to a specific data type, for which the TryParse family of functions have been designed.

= operator applied to nullable types in VB [duplicate]

In VB.NET this happens:
Dim x As System.Nullable(Of Decimal) = Nothing
Dim y As System.Nullable(Of Decimal) = Nothing
y = 5
If x <> y Then
Console.WriteLine("true")
Else
Console.WriteLine("false") '' <-- I got this. Why?
End If
But in C# this happens:
decimal? x = default(decimal?);
decimal? y = default(decimal?);
y = 5;
if (x != y)
{
Debug.WriteLine("true"); // <-- I got this -- I'm with you, C# :)
}
else
{
Debug.WriteLine("false");
}
Why is there a difference?
VB.NET and C#.NET are different languages, built by different teams who have made different assumptions about usage; in this case the semantics of a NULL comparison.
My personal preference is for the VB.NET semantics, which in essence gives NULL the semantics "I don't know yet". Then the comparison of 5 to "I don't know yet". is naturally "I don't know yet"; ie NULL. This has the additional advantage of mirroring the behaviour of NULL in (most if not all) SQL databases. This is also a more standard (than C#'s) interpretation of three-valued logic, as explained here.
The C# team made different assumptions about what NULL means, resulting in the behaviour difference you show. Eric Lippert wrote a blog about the meaning of NULL in C#. Per Eric Lippert: "I also wrote about the semantics of nulls in VB / VBScript and JScript here and here".
In any environment in which NULL values are possible, it is imprtant to recognize that the Law of the Excluded Middle (ie that A or ~A is tautologically true) no longer can be relied on.
Update:
A bool (as opposed to a bool?) can only take the values TRUE and FALSE. However a language implementation of NULL must decide on how NULL propagates through expressions. In VB the expressions 5=null and 5<>null BOTH return false. In C#, of the comparable expressions 5==null and 5!=null only the second first [updated 2014-03-02 - PG] returns false. However, in ANY environment that supports null, it is incumbent on the programmer to know the truth tables and null-propagation used by that language.
Update
Eric Lippert's blog articles (mentioned in his comments below) on semantics are now at:
Sep. 30, 2003 - A Whole Lot of Nothing
Oct. 1, 2003 - A Little More on Nothing
Because x <> y returns Nothing instead of true. It is simply not defined since x is not defined. (similar to SQL null).
Note: VB.NET Nothing <> C# null.
You also have to compare the value of a Nullable(Of Decimal) only if it has a value.
So the VB.NET above compares similar to this(which looks less incorrect):
If x.HasValue AndAlso y.HasValue AndAlso x <> y Then
Console.WriteLine("true")
Else
Console.WriteLine("false")
End If
The VB.NET language specification:
7.1.1 Nullable Value Types
... A nullable value type can contain the same values as the non-nullable
version of the type as well as the null value. Thus, for a nullable
value type, assigning Nothing to a variable of the type sets the value
of the variable to the null value, not the zero value of the value
type.
For example:
Dim x As Integer = Nothing
Dim y As Integer? = Nothing
Console.WriteLine(x) ' Prints zero '
Console.WriteLine(y) ' Prints nothing (because the value of y is the null value) '
Look at the generated CIL (I've converted both to C#):
C#:
private static void Main(string[] args)
{
decimal? x = null;
decimal? y = null;
y = 5M;
decimal? CS$0$0000 = x;
decimal? CS$0$0001 = y;
if ((CS$0$0000.GetValueOrDefault() != CS$0$0001.GetValueOrDefault()) ||
(CS$0$0000.HasValue != CS$0$0001.HasValue))
{
Console.WriteLine("true");
}
else
{
Console.WriteLine("false");
}
}
Visual Basic:
[STAThread]
public static void Main()
{
decimal? x = null;
decimal? y = null;
y = 5M;
bool? VB$LW$t_struct$S3 = new bool?(decimal.Compare(x.GetValueOrDefault(), y.GetValueOrDefault()) != 0);
bool? VB$LW$t_struct$S1 = (x.HasValue & y.HasValue) ? VB$LW$t_struct$S3 : null;
if (VB$LW$t_struct$S1.GetValueOrDefault())
{
Console.WriteLine("true");
}
else
{
Console.WriteLine("false");
}
}
You'll see that the comparison in Visual Basic returns Nullable<bool> (not bool, false or true!). And undefined converted to bool is false.
Nothing compared to whatever is always Nothing, not false in Visual Basic (it is the same as in SQL).
The problem that's observed here is a special case of a more general problem, which is that the number of different definitions of equality that may be useful in at least some circumstances exceeds the number of commonly-available means to express them. This problem is in some cases made worse by an unfortunate belief that it is confusing to have different means of testing equality yield different results, and such confusion might be avoided by having the different forms of equality yield the same results whenever possible.
In reality, the fundamental cause of confusion is a misguided belief that the different forms of equality and inequality testing should be expected to yield the same result, notwithstanding the fact that different semantics are useful in different circumstances. For example, from an arithmetic standpoint, it's useful to be able to have Decimal which differ only in the number of trailing zeroes compare as equal. Likewise for double values like positive zero and negative zero. On the other hand, from a caching or interning standpoint, such semantics can be deadly. Suppose, for example, one had a Dictionary<Decimal, String> such that myDict[someDecimal] should equal someDecimal.ToString(). Such an object would seem reasonable if one had many Decimal values that one wanted to convert to string and expected there to be many duplicates. Unfortunately, if used such caching to convert 12.3 m and 12.40 m, followed by 12.30 m and 12.4 m, the latter values would yield "12.3", and "12.40" instead of "12.30" and "12.4".
Returning to the matter at hand, there is more than one sensible way of comparing nullable objects for equality. C# takes the standpoint that its == operator should mirror the behavior of Equals. VB.NET takes the standpoint that its behavior should mirror that of some other languages, since anyone who wants the Equals behavior could use Equals. In some sense, the right solution would be to have a three-way "if" construct, and require that if the conditional expression returns a three-valued result, code must specify what should happen in the null case. Since that is not an option with languages as they are, the next best alternative is to simply learn how different languages work and recognize that they are not the same.
Incidentally, Visual Basic's "Is" operator, which is lacking in C, can be used to test for whether a nullable object is, in fact, null. While one might reasonably question whether an if test should accept a Boolean?, having the normal comparison operators return Boolean? rather than Boolean when invoked on nullable types is a useful feature. Incidentally, in VB.NET, if one attempts to use the equality operator rather than Is, one will get a warning that the result of the comparison will always be Nothing, and one should use Is if one wants to test if something is null.
May be
this
post well help you:
If I remember correctly, 'Nothing' in VB means "the default value". For a value type, that's the default value, for a reference type, that would be null. Thus, assigning nothing to a struct, is no problem at all.
This is a definite weirdness of VB.
In VB, if you want to compare two nullable types, you should use Nullable.Equals().
In your example, it should be:
Dim x As System.Nullable(Of Decimal) = Nothing
Dim y As System.Nullable(Of Decimal) = Nothing
y = 5
If Not Nullable.Equals(x, y) Then
Console.WriteLine("true")
Else
Console.WriteLine("false")
End If
Your VB code is simply incorrect - if you change the "x <> y" to "x = y" you will still have "false" as the result. The most common way of expression this for nullable instances is "Not x.Equals(y)", and this will yield the same behavior as "x != y" in C#.

What are the implicit type conversion rules in vba?

I know the following is possible in vba:
If Len(str) Then
Len(str) will evaluate to false if Len(str) is 0, true otherwise.
What are the exact conversion rules for vba? Please provide a link to official documentation if possible.
A boolean variable can have only two states, True and False. That's true in all programming languages (except if a nullable datatype exists, eg bool? in C# where the variable can have also the value null signaling it is not defined).
In VBA, a boolean is stored as 16-bit integer. False is defined as 0 and True as -1. Thats similar in other languages, simply because 0 has all bits set to 0 and -1 has all bits set to 1. But this is an implementation detail and your programming should not care about it. You deal with True and False and Boolean algebra using AND, OR and NOT.
Implicit conversion rules are straight forward: Numeric data types are converted to boolean False if they are 0 and to True in all other cases (that is, if the value has any bit set to 1). Converting a boolean value to a number results in 0 resp. -1.
Dim i As Integer
Dim b As Boolean
i = 3
b = i ' Implicit conversion from 3 to TRUE
i = b ' Implicit conversion from TRUE to -1
Strings are converted to numbers first, and if that fails, you get a runtime error. Dates are implemented as numbers (Double) in VBA, so every date/time is True except the date+time that is represented as 0 (that is 30 Dec 1899 00:00)
But from my point of view (and >30 years of programming), implicit conversions are evil and should be avoided. They are source of numerous errors, they lead to code that is harder to read - and there is simply no reason to rely on implicit conversations. There is no reason to write If len(str) Then. You want to check if the length of a string is greater than 0, so write it: If len(str) > 0 Then. Always.
Have a look to the following example: Obviously, the VBA runtime need to execute an implicit conversion, but can you tell the outcome?
Dim i As Integer
Dim b As Boolean
i = 3
b = i
If b = i Then Debug.Print "B=I"
Here you can find the official documentation from Microsoft: https://learn.microsoft.com/en-US/office/vba/language/reference/user-interface-help/boolean-data-type
I came across this in a recent textbook I was reading on C++ - I'll add a link at the end. Although a different language, both have similarities to some degree. One of these similarities is what you call 'implicit type conversion' or more technically, type casting.
For any Boolean expression in your project when you compile your VBA project (Debug > Compile VBAProject) any nonzero value will be treated as the value true and will treat the value 0 as false. Essentially this comes down to the how the compiler treats these statesments and also to operator precedence rules as well as boolean expression rules.
For further reading please see below links:
Operator precedence
Boolean data type
In C++ (as far as I am aware) this term is called copy initialisation, you can read more here:
Copy initialization
The book that brought this deep thought recently:
Problem Solving with C++: The Object of Programming
I know this doesn't necessarily answer your question, but hopefully some of the references help.

How does If 1 = 2 = 3 Then (...) work

While coding in VB.NET i accidently wrote something like this into my code;
Dim a as integer = 1
Dim b as Integer = 2
Dim c as Integer = 3
If a = b = c Then
'.. some Code
End if
It did not give me an error so it looks like it is a part of the programming language (or programming itself) that I do not know.
My Question:
How does this statement work and what are good examples for a use-case of this code?
Edit:
Dim a as Integer = 1 = 2 = 3
This line also does not give me an error. MsgBox(a) shows me a 0
The Answer:
You can find it in the questions comments.
Yes, with Option Strict Off in effect (the default) that is a valid expression. In that mode, VB.NET behaves (almost) like a dynamic language in the spirit of Javascript, Python or Ruby. The compiler emits conversions where needed to make the expression valid, readily converting between strings, booleans and numeric types.
The expression is evaluated left-to-right, in other words (a = b) = c. The a = b subexpression generates Boolean, it needs to be converted to Integer to make the comparison with c valid. False produces 0, True produces -1. Not a typo btw, part of the legacy when VB was still heavily based on COM automation.
The final expression type is Boolean again. Note how your second statement requires that to be converted to Integer. Since a = b with the given values always produces False, 0 = c will always be False.
With Option Strict On in effect, the compiler no longer applies these automatic conversions and generates an error on this statement. It insists you use CInt() to convert the Boolean sub-expression. Invariably good enough to discover that you fumbled the expression.
You probably ought to consider changing the default if mishaps like this byte frequently. Use Tools > Options > Projects and Solutions > VB Defaults > Option Strict setting. Beware that it will be hard to ever switch back :)

Why not to use a 'Return' statement in 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.