Someone didn't know about case statments..
-
Hi All,
I was looking through some example code for .NET GIS libary and came acros this:
If cmd = "" Then
Return
Else
If System.String.Compare(cmd, 0, "#", 0, 1, True) = 0 Then
Return
Else
If System.String.Compare(cmd, 0, "select ", 0, 7, True) = 0 Then
DoSelect(cmd)
Else
If System.String.Compare(cmd, 0, "insert ", 0, 7, True) = 0 Then
DoNonQuery(cmd)
Else
If System.String.Compare(cmd, 0, "update ", 0, 7, True) = 0 Then
DoNonQuery(cmd)
Else
If System.String.Compare(cmd, 0, "delete ", 0, 7, True) = 0 Then
DoNonQuery(cmd)
Else
If System.String.Compare(cmd, 0, "ExecuteScalar ", 0, 14, True) = 0 Then
DoExecuteScalar(cmd)
Else
If System.String.Compare(cmd, 0, "open ", 0, 5, True) = 0 Then
DoOpen(cmd)
Else
If System.String.Compare(cmd, 0, "close ", 0, 6, True) = 0 Then
DoClose(cmd)
Else
If System.String.Compare(cmd, 0, "help", 0, 4, True) = 0 Then
DoHelp()
Else
If System.String.Compare(cmd, 0, "set ", 0, 4, True) = 0 Then
DoSet(cmd)
Else
If System.String.Compare(cmd, 0, "prepare ", 0, 8, True) = 0 Then
DoPrepare(cmd)
Else
If System.String.Compare(cmd, 0, "schema", 0, 6, True) = 0 Then
DoGetSchemaTable()
Else
If System.String.Compare(cmd, 0, "path ", 0, 5, True) = 0 Then
DoSetPath(cmd)
Else
If System.String.Compare(cmd, 0, "pack ", 0, 5, True) = 0 Then
DoPack(cmd)
Else
_output.WriteLine(("Unknown command: " + cmd))
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
End IfI don't think they knew how to use a Case statment, I know that the above code will do the same as a Select Case but a least case statments make your code a hell of a lot easier to read.
Happy coding
Nathan
-
Most languages don't allow anything but basic types for the switch condition, so strings are out. I know the .NET languages allow strings too, but most people used to other languages are probably not aware of that. Apparently internally the compiler creates pretty much the above code anyway, except for a large number of strings when it's faster to hash the strings and go back to the "normal" numerical switch. That'd also be multi-language solution, but maintaining hashes of strings seems kinda painful :)
-
I know that the above code will do the same as a Select Case but a least case statments make your code a hell of a lot easier to read.
Even using elseifs would make it look much better :P
-
@Daniel15 said:
Even using elseifs would make it look much better
As an immediate fix, I agree that ElseIf would've cleaned this up. I'm sure there's something else that can be done, though, but I can't think of it at the moment.
-
In most programming languages, there is no such thing as an "else if". In C/C++/Java and all languages that define elseif as "else" followed by "if", there is only an "if" with an optional else. The "else if" construct is just another if nested inside the else clause. In those languages (and maybe also the one used there), the only thing that makes a difference between an "else if" and an else with a nested if is the way you layout your code.
-
@Nandurius said:
Most languages don't allow anything but basic types for the switch condition, so strings are out.
One possible trick to get around this is (pseudocode)
switch (true)
case s == "foo":
// do stuff
break;
case s == "bar":
// do stuff
break;
default:
// do stuff
end switch
-
@emurphy said:
@Nandurius said:
Most languages don't allow anything but basic types for the switch condition, so strings are out.
One possible trick to get around this is (pseudocode)
switch (true)
case s == "foo":
// do stuff
break;
This will not work in C/C++ or Java (IIRC). The case labels have to be integer constants or constant expressions.
-
@LordOfThePigs said:
In most programming languages, there is no such thing as an "else if".
That doesn't matter. The issue at hand is .NET, which does have an "ElseIf".
-
Yeah, the title is wrong, as the fix is elseif, not case. Or at least the indenting could have been done in a saner way so it doesn't creep to the right. Imagine adding a few new features - before long, the code will be off the side of the screen.
-
@AbbydonKrafts said:
@Daniel15 said:
Even using elseifs would make it look much better
As an immediate fix, I agree that ElseIf would've cleaned this up. I'm sure there's something else that can be done, though, but I can't think of it at the moment.
If the language has a map data structure and first-class functions (or at least function pointers or Java's anonymous classes), you can use a dispatch table.
-
@ailivac said:
If the language has a map data structure and first-class functions (or at least function pointers or Java's anonymous classes), you can use a dispatch table.
Or use a Real Language (*cough*Ruby*cough*) that allows anything in a switch statement. I mean, can your precious language of choice do this?
-
@AbbydonKrafts said:
That doesn't matter. The issue at hand is .NET, which does have an "ElseIf".
I'm completely unfamiliar with the language used here, but why is it calling out to the string compare function? Does == not work with strings or something?
-
@morbiuswilters said:
I'm completely unfamiliar with the language used here, but why is it calling out to the string compare function? Does == not work with strings or something?
Worse. VB.NET doesn't even have a == operator.
-
@bstorer said:
Or use a Real Language (*cough*Ruby*cough*) that allows anything in a switch statement. I mean, can your precious language of choice do this?
You know, I wish somebody would just "fix" case. The implicit breaks in Ruby are nice, but that "overload the array operator" hack seems really gross. Why not just something like myah:
switch (string) { case "foo": do_x(); case "bar", "baz": do_y(); default: print("omg errorz!\n"); exit(1); }
-
-
@morbiuswilters said:
@bstorer said:
Worse. VB.NET doesn't even have a == operator.
Now you're just fucking with me.
LMAO... no. VB doesn't use "==". It uses "=" for assignment AND comparison. However, the other languages in .NET do have "==".
Also, I use string.Compare in C# instead of ==. Dunno why.
-
@AbbydonKrafts said:
LMAO... no. VB doesn't use "==". It uses "=" for assignment AND comparison. However, the other languages in .NET do have "==".
Also, I use string.Compare in C# instead of ==. Dunno why.Ahh, well that's not as bad. In fact, it's arguably better than == for comparison because at least you would avoid junk like "if (x = y)" from C.
-
@morbiuswilters said:
You know, I wish somebody would just "fix" case. The implicit breaks in Ruby are nice, but that "overload the array operator" hack seems really gross. Why not just something like myah:
You can do that. See:a = "fish"
case a
when "cat"
puts "cat"
when "dog", "fish"
puts "dogfish"
when *["Bob","Joe","Steve"]
puts "Howdy!"
else
puts "No dice!"
endThis outputs "dogfish". Also, note the case under that: this works, too, without overloading any operators.
-
@morbiuswilters said:
Ahh, well that's not as bad. In fact, it's arguably better than == for comparison because at least you would avoid junk like "if (x = y)" from C.
Python does the same thing.
-
VB has object.Jam(it), right?
-
@bstorer said:
This outputs "dogfish". Also, note the case under that: this works, too, without overloading any operators.
Ahh, that's awesome, then. I guess I misunderstood what you linked to because I didn't understand why you'd even need an array if you could just use a comma-separated list. Ruby has some nice features but I'm not terribly fond of languages that use keywords instead of parens/braces/etc.. to separate blocks. I like learning new languages but I have pretty much everything I need between PHP and C and at this point I know them so well inside-and-out that I can be much more effective than in a new language.
-
@morbiuswilters said:
If you read further down on the link I posted, somebody corrects the OP about it. But I just needed a good example of the things Ruby lets you do, and that one had the bonus of introducing a major WTF.@bstorer said:
This outputs "dogfish". Also, note the case under that: this works, too, without overloading any operators.
Ahh, that's awesome, then. I guess I misunderstood what you linked to because I didn't understand why you'd even need an array if you could just use a comma-separated list.
@morbiuswilters said:
Ruby has some nice features but I'm not terribly fond of languages that use keywords instead of parens/braces/etc.. to separate blocks. I like learning new languages but I have pretty much everything I need between PHP and C and at this point I know them so well inside-and-out that I can be much more effective than in a new language.
I always liked Smalltalk, and Ruby steals many of Smalltalk's better features and mixes them with Perl. It's very freeing in some ways. But it can also be extremely frustrating, just like any other language.
-
@NathanW said:
I don't think they knew how to use a Case statment, I know that the above code will do the same as a Select Case but a least case statments make your code a hell of a lot easier to read.
And I don't think you know how to read APIs:
The variation of System.String.Compare used here compares to substrings of given length starting at the given positions in the compared strings. Switches in .NET only allow constant expressions to be used as case labels, so while .NET does allow constant strings, there's no way besides an 'elseif' construct to handle this problem.The real WTF is the use of System.String.Compare when System.String.StartsWith should have been used.
-
What about catfish?
-
@Ragnax said:
The real WTF is the use of System.String.Compare when System.String.StartsWith should have been used.
Why not just take the first 5 characters and lowercase them?
-
Obviously this is a perfect opportunity for the Enterprise compliant Switch Pattern.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public abstract class Switch
{
List<Case> cases = new ArrayList<Case>();
public Switch()
{
configureCases();
}
protected abstract void configureCases();
public void switchString(String cmd)
{
if( cmd == null)
return;
for( Case c : cases)
{
if(cmd.startsWith(c.getName()))
{
c.run(cmd);
return;
}
}
DoUnknown(cmd);
}
protected abstract void DoUnknown(String cmd);
void addCase(Case c)
{
cases.add(c);
}
abstract class Case
{
private String name;
public Case(String name)
{
this.name = name;
}
public abstract void run(String cmd);
public String getName()
{
return name;
}
}
public static void main(String[] args) throws Exception
{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
Switch sqlSwitcher = new Switch(){
@Override
protected void configureCases()
{
addCase(new Case("select"){public void run(String cmd){ DoSelect(cmd); }});
addCase(new Case("insert"){public void run(String cmd){ DoNonQuery(cmd); }});
addCase(new Case("update"){public void run(String cmd){ DoNonQuery(cmd); }});
addCase(new Case("delete"){public void run(String cmd){ DoNonQuery(cmd); }});
addCase(new Case("ExecuteScalar"){public void run(String cmd){ DoExecuteScalar(cmd); }});
addCase(new Case("open"){public void run(String cmd){ DoOpen(cmd); }});
addCase(new Case("close"){public void run(String cmd){ DoClose(cmd); }});
addCase(new Case("help"){public void run(String cmd){ DoHelp(cmd); }});
addCase(new Case("set"){public void run(String cmd){ DoSet(cmd); }});
addCase(new Case("prepare"){public void run(String cmd){ DoPrepare(cmd); }});
addCase(new Case("schema"){public void run(String cmd){ DoGetSchemaTable(cmd); }});
addCase(new Case("path"){public void run(String cmd){ DoSetPath(cmd); }});
addCase(new Case("pack"){public void run(String cmd){ DoPack(cmd); }});
}
protected void DoNonQuery(String cmd) {
System.out.println("DoNonQuery: " + cmd);
}
protected void DoSelect(String cmd) {
System.out.println("DoSelect: " + cmd);
}
protected void DoExecuteScalar(String cmd) {
System.out.println("DoExecuteScalar: " + cmd);
}
protected void DoOpen(String cmd) {
System.out.println("DoOpen: " + cmd);
}
protected void DoClose(String cmd) {
System.out.println("DoClose: " + cmd);
}
protected void DoHelp(String cmd) {
System.out.println("DoHelp: " + cmd);
}
protected void DoSet(String cmd) {
System.out.println("DoSet: " + cmd);
}
protected void DoPrepare(String cmd) {
System.out.println("DoPrepare: " + cmd);
}
protected void DoGetSchemaTable(String cmd) {
System.out.println("DoGetSchemaTable: " + cmd);
}
protected void DoSetPath(String cmd) {
System.out.println("DoSetPath: " + cmd);
}
protected void DoPack(String cmd) {
System.out.println("DoPack: " + cmd);
}
protected void DoUnknown(String cmd) {
System.out.println("Unknown command: " + cmd);
}
};
while(true)
{
sqlSwitcher.switchString(in.readLine());
}
}
}For even better extendability, add XML.