| « Prev | Page 1 | Page 2 | Next » |
|
They are obviously wanting to simulate an IF-ELSIF-ELSE structure, and
they must think that this SELECT CASE TRUE makes the code shorter or somehow neater. I can't think of any other possible reason for this madness. In languages with braces and whatnot, a SELECT/SWITCH can make it shorter, but I don't _really_ believe that's what is happening here. :p |
|
For those of us that aren't VB programmers, can someone explain what exactly Select Case True means? |
It will go down the list of cases until it finds one that evaluates to true and then execute it. I am guessing that in VB the 'break' is implicit? switch ( true ){ case a == b: //blah break; case c == d: //foo break; } means if ( a == b ) //blah else if ( c == d ) //foo |
|
That means it will hit the Case line that evaluates to True. Now, to be completely fair, Select Case True is currently necessary in VB.NET to do Type evaluation in a Select Case construct: Select Case True Case TypeOf MyObject Is MyType Etc.. End Select Clearly, of course, one could use If/Then/ElseIf.. |
switch (true) { case somethingThatEvaluatesToABoolean(): doSomething; break; } |
Re: A Truly Selective Case
2005-04-20 14:32
•
by
Charles Nadolski
|
|
Forgive my noobishness, but isn't use of a COM object a WTF in and of itself? Something that is to be avoided if possible?
|
Select Case objLoginValidation.error |
|
What exactly is the complaint about this code? "It looks strange" is a weak reason.
Switch statements are equivalent to if/elseif/elseif/.../else. Some languages (like Perl) do not have switch statements at all. The CPU treats everything like a goto in the end, but nobody would argue that everything should be done with only gotos. So why should all switch statements be done with only if/else statements? |
You are correct.
|
Not really, and not that uncommon when it comes to logging in (authenticating against a domain?) |
I can't really comment on whether this is a WTF because all VB code looks like a WTF to me. [;)] But switch case is not equivalent to if-else in all languages even though it can generally be replaced by them. Switch case statements are generally used in Java because they are 'faster' than chained if-else (at least theoretically.) |
We're not saying all switch statements should be done with If/Else statements. But Select Case True or switch(true) robs the switch case statement of any space-saving benefit it would have while making the code more confusing to read. Anonymous software guy has it pretty well. |
|
That suggests an especially evil variation:
|
|
The WTF is that switch should make a choice based on the variable
supplied. That is its purpose. It should not make a choice based on which complex case evaluates to a given constant. This makes the code hard to read, because it is not longer clear from the switch head what is done. Praise C/C++, where switch only works on constant cases :) |
For one, it was totally unecessary to even use "select case true" in this example, as software guy pointed out. That would be my complaint about this code, exactly. Plus, doing something that looks strange, whilst there is a perfectly well accepted non-strange-looking way of doing the (in effect) the same thing, it's a bad idea, because it effects readability for one, and can put silly notions in to the less informed mind (like a fresh junior dev or something). "Keep it simple, keep it safe" my grand-daddy's lesbo mothers friend use to say. |
I agree - the code does look strange, and anonymous software guy shows the way the select/case should be coded, and the unsafe error messages that are displayed are not good either - but code itself isn't much of a WTF. Now, the clearing out of strings, that's a different story.... |
use Switch; |
It's amazing how often I see this type of thing in our contractors' code. Initializing things before they are initialized. This is really annoying when it's a local variable because the compiler will tell you if there is a path that doesn't ensure initialization and doing this defeats that feature. |
|
I've been told by a couple people that switch(true) is
actually a *more efficient* method of handling some types of multiple exclusive tests than with if/elseif/elseif/elseif/elseif/ese. I don't recall the explanation exactly; something about the structuring of switch/select "tables" as seen by the compiler/parser being a more efficient way for the compiler/parser to jump to the correct peice of code. So to me the Select Case True is not such a strange thing to see.. BUT in this code, that doesn't stand up.. What really is WTF about this is that they did not "Select Case objLoginValidation.error" since that is the *only* variable they are comparing. In this case, a Select Case True is not properly used for the optimization I heard of, if it exists. Then to be even weirder, they provide "Case Else" for "Select Case True". It's like putting random checks in your code saying If(true == false) { Error('OMGWTF Somethings wrong!'); } |
|
ok, I agree the above is a WTF b/c it is more readable to have
select case Value but I have used select case True in the past. I evaluate code
So, in this instance: If TypeOf ctl Is ListBox Or TypeOf ctl Is ComboBox Then I find the select case slightly more readable (IMO). |
|
I think the time on the web server is off. The timestamps on the posts look wrong.
|
Looks like GMT (or the DST version maybe) to me. |
If I'm not mistaken, "Case Else DoBlah" on a "Select Case True" doesn't mean, "in the case that True is not True, DoBlah" but rather, "in the case that none of the above conditions evaluated to True, DoBlah." As for at the second part of the WTF: When I was in college taking computer science courses one of my professors told us about a bajillion times each semester to always, always, initialize our variables explicitly. Now, even though I'm out of college and I know that that isn't always necessary, I still find myself doing Dim Blah as Integer Dim Meh as String Blah = 0 Meh = "" every now and then. |
The optimization of switch case is that if you take an integral type and switch on it, the compiler can build a 'jump table' that allows if you jump directly to the correct instruction without check the preceeding cases. Like if you are testing 1, 2, 3 and 4 and you pass in 4, it can jump ahead 4x memory slots to the corresponding instruction (this is a very oversimplified explanation) instead of check 1, 2, and 3. By the very nature of the select case statement, it cannot have this optimization. It is, as far as I can tell, purely syntactical sugar. |
I'm not quite sure whether this is serious or a joke. It is actually a poor security practice to explain why authentication has failed, since it gives an attacker useful information. |
|
We have a lot of people who like to do this in java:
They thought that if they didn't set everything to null before the method returned, the objects might never get garbage collected, because that method had a reference to them.... |
|
I'm surprised there are some defenders of the Select Case code. Actually that's a lie, I'm never surprised. I see some of the strangest code defended on a regular basis. Does the code compile? Sure. Will it work? Yep. Does it look weird? That's an opinion issue. Is this how "Select Case" was intended to be used? Absolutely not. It's that last part that makes this a WTF. If/Else If/Else and Select Case are both selection structures, so you may be able to swap them out in just about any situation. The point is that If/Else If/Else was intended for making comparisons on different sets of circumstances or groups of data, and Select Case was intended for a limited set of options for a single data value. 'An If statement works better for this kind of criteria If MyAge > 60 Then 'Use selection struction for limited, predefined possibilities Select Case CurrentDayOfTheWeek You could always use a For or Do loop to add two numbers together (loop through, incrementing your variable as many times as the number you want to add to it), but why would you do that when you can just make that plus sign do what it was intended to do? Just because it isn't broken doesn't make it OK. |
One of my favorite Perl features. |
|
Obviously in this particular case, Select Case objLoginValidation.error should have been used. Nonetheless, Select Case True can be a useful feature in VB 6. It allows lazy evaluation. If x = 1 OR y = 2 OR z = 3 Then will evaluate all three conditions in VB 6. Select Case True Case x = 1, y = 2, z = 3 will lazy evaluate (so if x = 1 then y and z won't be checked). Note that the comma is essentially equivalent to OR.
|
|
I have never seen that documented anywhere, but sure enough it's true. VB is known for not having short-circuiting, but I'll be damned if it works in the Select Case situation. |
OOo, I didn't know that. That's a pretty cool trick--short circuit evaluating in VB6. I sometimes use Select Case even when there is only one real 'case' I am interested in. Like when I have to check for a range or set of values. Instead of If medCode = 320 OR medCode = 331 OR (medCode => 412 AND medCode <= 420) OR medCode = 499 Then I can do: Select Case medCode This is especially helpful if there are 30+ valid values to check. I wish I could just use the SQL "IN" syntax: |
In Perl 6, you will be able to! |
|
I personally am quite fond of the SELECT CASE TRUE structure in VB
(though I don't use it, I have seen it used in code I have maintained.) I've also seen some gothic (as in elaborate) examples of its use. For instance, there is a guy in the newsgroups (go find it yourself) who demonstrates the use of SELECT CASE TRUE for performing sanity checks in a function. Code runs something like this: SELECT CASE TRUE CASE Err.Number = SOME_KNOWN_ERROR ' Deal with the known error CASE Err ' Deal with some other unknown error CASE iSuppliedValue = 0 ' Deal with some non-supplied value CASE strOutputFile = "" ' Deal with lack of filename ... CASE ELSE ' Proceed with normal code. END SELECT The argument is that this makes it unnecessary to use EXIT FUNCTION statements, or otherwise play with the flow, and that it is easy to add new conditions to the code later. HOWEVER, the biggest problem with SELECT CASE TRUE is that it is not supported in most other languages. This would make rewriting the above code for another language a bit onerous. So I decided to not use the construction myself. |
Me too. And I still do it a lot (although not in SQL). I get that there isn't any real advantage to doing it in many cases, but does it cause any significant negative impact on the code in question? I'm honestly curious because I have the habit, and I want to know if I'm doing something truly embarrassing--I already generate my share of WTF candidate code as it is. |
|
I'm not sure I trust that code since a mathemetician once told me that 1 + 1 = 3 for sufficiently large values of 1 :-).
|
did you forget your sarcasm tags? [:p] |
|
Looks like the programmer was just wishing they could use Lisp.
|
|
"I have never seen that documented anywhere, but sure enough it's true. VB is known for not having short-circuiting, but I'll be damned if it works in the Select Case situation." I believe Code Complete makes mention that changing if-then-elses to switches speeds up VB code. Where as it drastically slows Java code. If I manage to be able to leave work tonight, I can dig up the benchmarks they provide otherwise I'll leave that as an excercise for the reader.
|
|
I have not looked at VB.Net but this is a truely VB again - I mean having a valid language statement like select case true just boggels the mind Maybe we should rather WTF the guy doing the language semantics.
But on a more objective note - back in the old days .... now I really mean long ago when I was young and Intel was still doing 4 bit processors, memory was stil a factor in programming and tight code was cool, switch (select case or what ever - depending on the language) statements resulted in neat jump tables when the compiler started spitting out machine code. Most of the time this generted more efficient code than any if else elseif bla bla bla at nausium would generate. My $0.02 |
|
Gentlemen,
Calm down. I agree that to a non-VB6 guy this looks weird. But there is a perfectly valid reason for using type of select statement -- You get INTELLISENSE. The moment you type in Case objLoginValidation.error = the enum intellisense pops up. If you coded it the "correct" way: you would get no Intellisense whatsoever. |
Maybe this means that intellisense isn't always intelligent and doesn't always make sense? ;) |
|
Freaky. Delphi is smarter, then. after you type case SomeExpression of and press Ctrl+Space, you get a list of the possible values to use. Quite helpful.
|
You would actually get intellisense... in VB.NET Drak
|
Actually this is not really a bad practice, maybe a strange habit in this case, but clearing strings is often enough used (eg.: in C++). If you don't, strange things can happen. |
|
IIRC, I have seen example such as this in the MSDN. That's how you are SUPPOSED to do it (at least according to M$).
The again, the MSDN is also a WTF in my opinion (especially dynamic help!!) These days I have two versions of the MSDN on my machine (one for VC7 and one for VC6, because the VC7 prefers to give me .NET junk instead of the standard C++ functions) and I still can't find anything. :( Anyway, doing something just to please intellisense is senseless (pun intended) and a WTF all by itself. Please don't program to please intellisense. Pretty please. |
Very nerdy stuff below. Not for the faint of heart ! It would still be more efficient, in most languages. You have to understand that VB (up until 4 (and again since 7)) was an interpreted language (just like Java). In non-interpreted languages, nice and neat jump tables makes sense, but when the interpreter has to interpret the code, the switch takes longer to execute. You don't really notice any significant (and by significant I mean microsecond) difference. e.g. ;switch case example ; switch (xxx) mov ax, [xxx] ; set ax = the value of xxx ;{ ; case 0: cmp ax, 0 ; see if ax equals 0 jz lb_lable1; if ax equals 0, jump to lb_label1 ; case 1: cmp ax, 1; see if ax equals 1 jz lb_lable2 ; if ax equals 1, jump to lb_lable2 ; default: jmp lb_default ; else, jump to lb_default In native code, the processor can simply jump to the correct location. In interpreted code, the interpreter first has to figure out where each of these labels will be, and then tell the processor about them. In interpreted code, the following will be faster on average, provided the first option get's chosen more often than the last option (meaning it doesn't have to go through all the if-else cases) ;if exaple ;if (xxx == 0) mov ax, xxx cmp ax, 0 jz lb_label1 ;else if (xxx == 1) mov ax, xxx cmp ax,1 jz lb_lable2 ;else jmp lb_default; If the first branch is taken, the interpreter only has to craete one jump point and make the processor jump there. The other issue with the intepreter is that there are context switches and paging involved, which slows things down quite a bit. These days, the official M$ line is "Who cares about resources ? Let your resources run out ! That means you will buy another PC, which will probably come with a copy of Windows(tm) bundled and make us some hard earned $$$$ !!!" |
|
That's nothing. Wait until you play with
Select Case False Makes a wonderful replacement for If test1 And test2 And test3 Then |
|
At least the 2005 DevStudio has an intelligent intellisense - there you
do not need to revert to this extreme to get a list of possible values |
I think the reason for this is that some primitive languages required that the contents of each variable be terminated with a NULL character so that the language would know when to stop reading. When assigning a value to a variable that already contained a value only the number of bytes actually supplied would be overwritten, so if the original contents were longer the surplus bytes would still remain. Thus the following two statements: var1 = "FIVE" var1 = "TEN" would result in the contents of var1 being "TENE". By setting the variable to '' (which was supposed to fill it with NULLs, not just set the first byte to NULL) you effectively erase the existing contents before inserting a new value. Thankfully modern languages are not so stupid, but some college professors are still behind the times and insist on using outdated practices. |
WTH? Generally used in Java? I mean - if you have it, you use it, why the f*ck shouldn't I use it as frequently in C as I do in Java, or any language that has some sort of switch/select-case construct? And anyway, someone using a case statement in Java only because it's faster has no clue about performance. Java itself isn't that slow u know, the problem is that java makes it easy to write a program in an inefficient way (C# has the same problem), and the early VM's weren't really that fast, but that changed a lot since then. When you want/need optimalisations, look at the source (not literaly [:P]) of the performance problems - which is in general the main program design - not always the implementation. Case statements should be used when comparing one variable value to multiple constant values, that's what it's there for, to make such a thing clear & readable. And this case-statement actually de-optimizes that case-statement, since the cpu has to evaluate each "case"-value also, which ends up in 2 compares. Not that you're gonna notice this (in any language that is) with the cpu's of today, and even on a 486 33mhz, you'll never notice this, certainly when it's only executed once in a login sequence... Oh no, the user should wait 0,00000001s longer - now he's gonna have a heart-attack! [*-)][:P] |
| « Prev | Page 1 | Page 2 | Next » |