After two years of C#, I'm now back to VB.net because of my current job. In C#, I can do a short hand testing for null or false value on a string variable like this:
if(!String.IsNullOrEmpty(blah))
{
...code goes here
}
however I'm a little confused about how to do this in VB.net.
if Not String.IsNullOrEmpty(blah) then
...code goes here
end if
Does the above statement mean if the string is not null or empty? Is the Not keyword operate like the C#'s ! operator?
In the context you show, the VB Not keyword is indeed the equivalent of the C# ! operator. But note that the VB Not keyword is actually overloaded to represent two C# equivalents:
logical negation: !
bitwise complement: ~
For example, the following two lines are equivalent:
C#: useThis &= ~doNotUse;
VB: useThis = useThis And (Not doNotUse)
Yes they are the same
Not is exactly like ! (in the context of Boolean. See RoadWarrior's remark for its semantics as one's complement in bit arithmetic). There's a special case in combination with the Is operator to test for reference equality:
If Not x Is Nothing Then ' … '
' is the same as '
If x IsNot Nothing Then ' … '
is equivalent to C#'s
if (x != null) // or, rather, to be precise:
if (object.ReferenceEquals(x, null))
Here, usage of IsNot is preferred. Unfortunately, it doesn't work for TypeOf tests.
They work identically until you reference C or C++ code.
For example doing NOT on the result of a Win32 API function, might lead to incorrect result, since true in C == 1, and a bitwise NOT on 1 does not equal false.
As 1 is 00000000001
Bitwise Not 11111111110
While false is 00000000000
However in VB it works just fine, as in VB true == -1
As -1 is 11111111111
Bitwise Not 00000000000
c# : boolean example1 = false;
boolean example2 = !example1;
vb.net: dim example1 as boolean = False
dim example2 as boolean = Not example1
Seconded. They work identically. Both reverse the logical meaning of the expression following the !/not operator.
Related
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
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#.
I always use AndAlso while checking multiple conditions as it doesn't evaluate right side unless left one is true. I don't see any situation where someone would like to evaluate right side even if left one fails. If it was needed then why they didn't include same in C#.
Update:
As accepted answer pointed out that it exists because it is used for bitwise operation, that fine enough but I still think they would have overloaded And operator to serve both purposes and just not created AndAlso. If anyone can pour some light on it, this question is still open :)
They included the same in C#. In C# you can use & (And) or && (AndAlso).
There's no real use case i can imagine for the not short-circuit operator when comparing booleans, but And can be used with numeric values, and it then does a bitwise comparison. That's why it exists. But when comparing boolean types, you'll always be using the short-circuit version.
And is also a bit operator. Here is an example showing a mix of And an AndAlso.
Dim foo? As Integer = 5
If foo.HasValue AndAlso (foo And 1) = 1 AndAlso (foo And 4) = 4 Then
Stop
End If
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 :)
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.