|
|
|
Why VB.NET suxx0r
|
Friday, April 14, 2006
|
WARNING! This blog post is written in anger and frustration !WARNING
I'm currently recovering from a near VB.NET experience. In a Swedish
forum somebody asked about casts from DbNull to concrete types and I
decided to swiftly put together an example function that could be
reused. The swiftly part was quickly omitted in the so called RAD
environment of VB.NET. Here is the story about why.
The function I was about to write was a simple check to see if the input parameter value of the type object was in the concrete form of DbNull. If it was, I would return 0 else it would use the Convert.ToInt64 function to return a Long (Yes I know that Int64.TryParse probably would've solved this quickly but I didn't go down that path for this example).
Since I've used VB and VB.NET some before I know about the IS operator
and I know about the IIF function built into the language. So my first
attempt looked something like this:
Return IIF ( value Is DbNull, 0, Convert.ToInt64(value) )
Standard C# code converted into VB.NET. Now that didn't compile at all in VB.NET, apparently the type name DbNull was not possible to use in the context of Is, that's fine by me. I didn't like the syntax semantics but it was purely syntax, nothing else. So I tried to use the typeof operator:
Return IIF( value Is typeof(DbNull), 0, Convert.ToInt64(value) )
No compile there either, it turns out that typeof has to be before an Is statement and can only be applied to objects. Now why I would need typeof to work for objects when there is an object.GetType() eludes me but so far it's all about my inexperience with VB.NET syntax and its quirks (it also annoys me that there is a Mid when we have string.Substring in the framework but that is another post ).
I found another keyword that supposedly would help me out; GetType, it works more like the typeof does in C# so I tried this out:
Return IIF(value is GetType(DbNull), 0, Convert.ToInt64(value) )
That actually compiled; joy! But function wise it failed miserably. The
convert was always called regardless of the type the object variable
contained. I factored out the type check to a regular If statement and discovered something that got me really puzzled.
If i changed it to Value Is GetType(object) it returned true. My god! It actually returned a check on the declaration of the parameter, not a check against the actual object type...
That gave me a serious headache. Still using the factored out version I
changed the type check again to instead make sure I get the concrete
type out of the variable
:
If typeof ( value ) is DbNull then
That gave me the expected result, what a relief! My trip to VB World
would soon be over. I refactored the code back to using the IIF
function:
Return ( typeof ( value ) is DbNull, 0, Convert.ToInt64(value) )
I compiled and run it and it blew up in my face. GAH! Frustration! At
this point I was about to give up, how is it possible that a type check
that works in a regular If statement would fail in the IIF call!?
Some quick research gave me the answer, it didn't differ how the type
check works. It turns out that the IIF function is one of the most
stupid functions in the whole language. It does not care about your
check at all; it goes ahead and evaluates both the false and the true
part of the IIF statement regardless of the expression result.
Why would I want that kind of behavior? One of the reasons for using an
if statement in the first place is to shield away the parts from each
other, in my case it actually tried to convert to long although the
check showed that it would not succeed.
A quick summary; type checks is really not intuitive in VB.NET, with
special behaviors it actually confuses the heck out of programmers, no
how's that for an "entry level language"? Additionally VB.NET functions
are really stupid and doesn't do what they appear to do, they do
something else. In a later post I'll show what =, Mid and other VB
stuff really does.
Down with VB.NET! Long live C#!
|
|
|
|
|
|
|
Comments
|
|
4/14/2006 8:23:00 PM
-
Jeff Certain
|
|
|
You definitely went about it the hard way. A quick read of DbNull would have revealed DbNull.Value.
Been a while since I played with this, but your function should look like:
Return (value is dbnull.value, 0, Convert.ToInt64(value) )
|
|
|
|
|
4/14/2006 8:29:00 PM
-
Jeff Certain
|
|
|
BTW, VB.NET developers know how to use intellisense. Since Value is the only member of DbNull, this probably would have solved your problem.
Seems to me the problem in this case is with the developer, not the language.
|
|
|
|
|
4/14/2006 8:31:00 PM
-
Jeff Certain
|
|
|
BTW, VB.NET developers know how to use intellisense. Since Value is the only member of DbNull, this probably would have solved your problem.
Seems to me the problem in this case is with the developer, not the language.
|
|
|
|
|
4/15/2006 12:55:00 AM
-
[anonymous]
|
|
|
|
Even worse. Is is actually a different kind of = ? That IMHO is really bad, you can use Is to check for types but also for values? Now I do understand the semantics of Is, when checking for types it actually checks to see if the object types reference the same type object in the CLR. But using Is as =, my god it is really a screwed up language. Also IIF still has the same problem, it will evaluate the convert call no mather what.
|
|
|
|
|
5/3/2006 2:43:00 PM
-
Ola
|
|
|
You were really close there Patrik.
This is how to do it.
If IsDBNull(value) Then
Else
End If
RTFM/STFW ;)
|
|
|
|
|
5/3/2006 2:44:00 PM
-
Ola
|
|
|
You were really close there Patrik.
This is how to do it.
If IsDBNull(value) Then
Else
End If
RTFM/STFW ;)
|
|
|
|
|
5/3/2006 2:46:00 PM
-
Ola
|
|
|
Oh BTW, your blog crashes if I uncheck "Remember me"
|
|
|
|
|
3/26/2007 9:39:00 PM
-
Rockoon
|
|
|
OMG learn what IIF() is!!
I'll lay 9:1 that in the future you will also have trouble with Shared vs Static.
These confusions arise when a programmer from C# land jumps into VB.NET thinking hes big macho C# programmer so VB should be a snap.
IIF() is a FUNCTION (as is common in BASIC dialects) so its no suprise that it behaves like one.
The lack of a ternary operator in VB.NET is for sure something the language development team should be embarassed about, but at least they have an excuse (most other dialects don't have one either, and some legacy code relies on IIF() behaving the way it always has)
|
|
|
|
|
3/26/2007 10:20:00 PM
http://www.lowendahl.net
-
Patrik Löwendahl
|
|
|
|
Yes and that is exactly why VB suxx. It's is still function oriented.
|
|
|
|
|
4/28/2007 12:47:00 AM
-
Al
|
|
|
|
You're comparing apples and oranges; IIf() isn't even part of VB.Net; it's part of the old VB Interaction module, and generally speaking shouldn't be used. Most of us stopped using it even prior to .Net, as it caused an additional module to load, and evaluated both conditions, even if the first part evaluated to True.
|
|
|
|
|
4/29/2007 2:14:00 PM
http://www.lowendahl.net
-
Patrik Löwendahl
|
|
|
Not really.
IIF might be calling a function in the compat library. But it is still incorporated as part of the language and the compiler treats it as a syntax element.
That is pure wrong in my opinion. If it is a function it should be call as such:
like: lameCompat.IIf()
|
|
Comment
|
|