By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,874 Members | 1,027 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,874 IT Pros & Developers. It's quick & easy.

switch on string value

P: n/a
Hi

i have a string variable which can take one of a set of many values.
Depending on the value I need to take different (but related) actions. So I
have a big if/else-if construct - but what is a better way of doing this?

if ("control" == commandString)
{
}
else if ("execute" == commandString)
{
}
else if ("send" == commandString")
{
}
else if ( ....

etc
Thanks,
Peter
Nov 29 '06 #1
Share this Question
Share on Google+
11 Replies


P: n/a
Well, switch (on a string) would automatically compile to a hashtable for
performance; however you could look at enums. Alternatively a dictionary of
delegates might be in order...

Marc
Nov 29 '06 #2

P: n/a
Marc Gravell wrote:
Well, switch (on a string) would automatically compile to a hashtable for
performance; however you could look at enums. Alternatively a dictionary of
delegates might be in order...

Marc

Enums seem appropriate here for simplicity, however these enum/switch
kind of scenarios are usually interchangeable with the Strategy pattern,
(if you're up to some more coding):

http://www.dofactory.com/Patterns/PatternStrategy.aspx

Wiebe
Nov 29 '06 #3

P: n/a
Tom
Short answer...this is how your switch would look

switch (commandString.ToLower())
{
case "control":
//do code unique to this case
FunctionCallToDoCommonCodeToAllCases();
break;
case "execute":
//do code unique to this case
FunctionCallToDoCommonCodeToAllCases();
break;
}

etc etc

Peter Kirk wrote:
Hi

i have a string variable which can take one of a set of many values.
Depending on the value I need to take different (but related) actions. So I
have a big if/else-if construct - but what is a better way of doing this?

if ("control" == commandString)
{
}
else if ("execute" == commandString)
{
}
else if ("send" == commandString")
{
}
else if ( ....

etc
Thanks,
Peter
Nov 29 '06 #4

P: n/a
Hi Peter

You should generally try not to switch on a string. As suggested
earlier it is better to convert your string to an enum

static public TNewEnum ConvertTo<TNewEnum>(object input)
{
return (TNewEnum)Enum.Parse(typeof(TNewEnum),
input.ToString(), true);
}

and then perform your switch on the enum

On Nov 30, 5:41 am, "Tom" <thomas.f.ty...@wamu.netwrote:
Short answer...this is how your switch would look

switch (commandString.ToLower())
{
case "control":
//do code unique to this case
FunctionCallToDoCommonCodeToAllCases();
break;
case "execute":
//do code unique to this case
FunctionCallToDoCommonCodeToAllCases();
break;
}

etc etc

Peter Kirk wrote:
Hi
i have a string variable which can take one of a set of many values.
Depending on the value I need to take different (but related) actions. So I
have a big if/else-if construct - but what is a better way of doing this?
if ("control" == commandString)
{
}
else if ("execute" == commandString)
{
}
else if ("send" == commandString")
{
}
else if ( ....
etc
Thanks,
Peter
Nov 29 '06 #5

P: n/a
ni***********@iinet.net.au wrote:
You should generally try not to switch on a string. As suggested
earlier it is better to convert your string to an enum

static public TNewEnum ConvertTo<TNewEnum>(object input)
{
return (TNewEnum)Enum.Parse(typeof(TNewEnum),
input.ToString(), true);
}

and then perform your switch on the enum
What extraordinary advice! Why do you say this? Do you imagine that a
switch on an enum is clearer? Surely you cannot imagine that this is
faster than switching on a string value?

Switching on a string value involves doing a series of inline
comparisons. The enum approach involves calling a method that calls a
method that gets a table of enum strings from metadata then scans that
table and boxes the result; then casts the boxed enum to an enum and
returns the unboxed enum; then doing a switch on the unboxed enum.

--

..NET 2.0 for Delphi Programmers
www.midnightbeach.com/.net
What you need to know.
Nov 29 '06 #6

P: n/a
I agree; I don't see the value of converting to an enum just to perform
the switching. However if these strings logically grouped per the
overall program design, then maybe making them an enum in the first
place is appropriate; i.e. "... different (but related) actions."

That said, I've always been a fan of "switch" over "if / else if".
IMHO it's easer to read, less error-prone during changing - especially
if the "if/else if" programmer doesn't use braces for single statement
branches; now the reader has to stop and think a bit to make sure (s)he
is reading it correctly. Finally there's the switch's "default" which,
for me, tends to make me code an error trap; yeah, I know "default" is
optional, but it's saved me a couple of times catching one of those
mythical "can't ever happen" errors.

On 2006-11-29 16:51:39 -0600, Jon Shemitz <jo*@midnightbeach.comsaid:
ni***********@iinet.net.au wrote:
>You should generally try not to switch on a string. As suggested
earlier it is better to convert your string to an enum

static public TNewEnum ConvertTo<TNewEnum>(object input)
{
return (TNewEnum)Enum.Parse(typeof(TNewEnum),
input.ToString(), true);
}

and then perform your switch on the enum

What extraordinary advice! Why do you say this? Do you imagine that a
switch on an enum is clearer? Surely you cannot imagine that this is
faster than switching on a string value?

Switching on a string value involves doing a series of inline
comparisons. The enum approach involves calling a method that calls a
method that gets a table of enum strings from metadata then scans that
table and boxes the result; then casts the boxed enum to an enum and
returns the unboxed enum; then doing a switch on the unboxed enum.

Nov 29 '06 #7

P: n/a
I think Bob has a really good point: readability. Switch seems to me
(and apparently Bob) to be the easiest to read and therefore maintain.

Other methods (enums, strategy pattern) are valid and I'm sure they
work. There are probably scalability and performance concerns. I think
enums may be fastest, although I have no proof either way. The strategy
pattern probably scales the best: no one wants to read a switch
statement with 100 possible values.

Look at the rest of the requirements. Is high performance essential,
which has the implied and must-be-tested meaning that a switch
statement is not fast enough? Are there a whole lot of switches? If
it's just a three-way split in a non-performance critical section,
switch is probably the simplest.
Stephan

Bob Jones wrote:
I agree; I don't see the value of converting to an enum just to perform
the switching. However if these strings logically grouped per the
overall program design, then maybe making them an enum in the first
place is appropriate; i.e. "... different (but related) actions."

That said, I've always been a fan of "switch" over "if / else if".
IMHO it's easer to read, less error-prone during changing - especially
if the "if/else if" programmer doesn't use braces for single statement
branches; now the reader has to stop and think a bit to make sure (s)he
is reading it correctly. Finally there's the switch's "default" which,
for me, tends to make me code an error trap; yeah, I know "default" is
optional, but it's saved me a couple of times catching one of those
mythical "can't ever happen" errors.

On 2006-11-29 16:51:39 -0600, Jon Shemitz <jo*@midnightbeach.comsaid:
ni***********@iinet.net.au wrote:
You should generally try not to switch on a string. As suggested
earlier it is better to convert your string to an enum

static public TNewEnum ConvertTo<TNewEnum>(object input)
{
return (TNewEnum)Enum.Parse(typeof(TNewEnum),
input.ToString(), true);
}

and then perform your switch on the enum
What extraordinary advice! Why do you say this? Do you imagine that a
switch on an enum is clearer? Surely you cannot imagine that this is
faster than switching on a string value?

Switching on a string value involves doing a series of inline
comparisons. The enum approach involves calling a method that calls a
method that gets a table of enum strings from metadata then scans that
table and boxes the result; then casts the boxed enum to an enum and
returns the unboxed enum; then doing a switch on the unboxed enum.
Nov 29 '06 #8

P: n/a
ssamuel wrote:
enums may be fastest
Only if the input is already an enum, but the OP specified a string.

Using Rick Fletcher's ConvertTo, I benchmark switch on string as
about 2.5 times faster than switch on enum-from-string.

// Shemitz.Utilities is available at
// www.midnightbeach.com/.net/source.code

using System;
using System.Collections.Generic;
using System.Text;
using Shemitz.Utilities;

namespace SwitchOnStringOrEnum
{
class Program
{
static void Main(string[] args)
{
const int Iterations = 10;

string Control = "CONTROL".ToLower(); // avoid interning ... strings should not be reference-equal
string Execute = "EXECUTE".ToLower();
string Send = "SEND".ToLower();

Method OnString = delegate
{
for (int Index = 0; Index < Iterations; Index++)
{
SwitchOnString(Control);
SwitchOnString(Execute);
SwitchOnString(Send);
}
};
Method OnEnum = delegate
{
for (int Index = 0; Index < Iterations; Index++)
{
SwitchOnEnum(Control);
SwitchOnEnum(Execute);
SwitchOnEnum(Send);
}
};

using (new Benchmark())
{
OnString();
OnEnum();
}

using (new Benchmark("Switch on string"))
OnString();
using (new Benchmark("Switch on enum"))
OnEnum();

Console.ReadLine();
}

private static int SwitchOnString(string Input)
{
switch (Input)
{
case "control":
return 0;
case "execute":
return 1;
case "send":
return 2;
default:
return -1;
}
}

private static int SwitchOnEnum(string Input)
{
switch (ConvertTo<Commands>(Input))
{
case Commands.control:
return 0;
case Commands.execute:
return 1;
case Commands.send:
return 2;
default:
return -1;
}
}

static public TNewEnum ConvertTo<TNewEnum>(object input)
{
return (TNewEnum)Enum.Parse(typeof(TNewEnum), input.ToString(), true);
}
}

delegate void Method();

enum Commands { control, execute, send };
}
--

..NET 2.0 for Delphi Programmers
www.midnightbeach.com/.net
What you need to know.
Nov 30 '06 #9

P: n/a
I neither suggested nor implied that Peter should implement the
solution as you have outlined. I merely stated that it is better to
switch on a enum rather than a string and provided a method by which
you could perform a conversion.

Obviously performing such an operation every time the switch is
evaluated is going to be slower.

On Nov 30, 11:42 am, Jon Shemitz <j...@midnightbeach.comwrote:
ssamuel wrote:
enums may be fastestOnly if the input is already an enum, but the OP specified a string.

Using Rick Fletcher's ConvertTo, I benchmark switch on string as
about 2.5 times faster than switch on enum-from-string.

// Shemitz.Utilities is available at
//www.midnightbeach.com/.net/source.code

using System;
using System.Collections.Generic;
using System.Text;
using Shemitz.Utilities;

namespace SwitchOnStringOrEnum
{
class Program
{
static void Main(string[] args)
{
const int Iterations = 10;

string Control = "CONTROL".ToLower(); // avoid interning ... strings should not be reference-equal
string Execute = "EXECUTE".ToLower();
string Send = "SEND".ToLower();

Method OnString = delegate
{
for (int Index = 0; Index < Iterations; Index++)
{
SwitchOnString(Control);
SwitchOnString(Execute);
SwitchOnString(Send);
}
};
Method OnEnum = delegate
{
for (int Index = 0; Index < Iterations; Index++)
{
SwitchOnEnum(Control);
SwitchOnEnum(Execute);
SwitchOnEnum(Send);
}
};

using (new Benchmark())
{
OnString();
OnEnum();
}

using (new Benchmark("Switch on string"))
OnString();
using (new Benchmark("Switch on enum"))
OnEnum();

Console.ReadLine();
}

private static int SwitchOnString(string Input)
{
switch (Input)
{
case "control":
return 0;
case "execute":
return 1;
case "send":
return 2;
default:
return -1;
}
}

private static int SwitchOnEnum(string Input)
{
switch (ConvertTo<Commands>(Input))
{
case Commands.control:
return 0;
case Commands.execute:
return 1;
case Commands.send:
return 2;
default:
return -1;
}
}

static public TNewEnum ConvertTo<TNewEnum>(object input)
{
return (TNewEnum)Enum.Parse(typeof(TNewEnum), input.ToString(), true);
}
}

delegate void Method();

enum Commands { control, execute, send };

}--

.NET 2.0 for Delphi Programmerswww.midnightbeach.com/.net
What you need to know.
Nov 30 '06 #10

P: n/a
"Peter Kirk" <pk@alpha-solutions.dkskrev i en meddelelse
news:ul**************@TK2MSFTNGP02.phx.gbl...
if ("control" == commandString)
{
}
else if ("execute" == commandString)
{
}
else if ("send" == commandString")
{
}
else if ( ....
Hi again. Thanks for all the comments. My code is a small part of a larger
system. I receive an object in my method, and in this object is a string
property which I must check to determine what action I should take. There is
a set of about 15 string values this property can take - but it is not an
enum, it is a string.

I guess I could convert to an "enum" value and use that, or I could have
just used switch/case. My initial code was simply a really long if/else
construct.

Now I have tried a dictionary of delegate methods. I really have no idea of
performance issues, but the code _appears_ cleaner in my class, due to the
fact that I don't have a huge if/else. I do however have a large constructor
where I initialise the dictionary... still, it was also the first time I
ever looked at delegates, so I consider it a learning experience.
thanks again,
Peter
Nov 30 '06 #11

P: n/a
Peter Kirk wrote:
I guess I could convert to an "enum" value and use that, or I could have
just used switch/case. My initial code was simply a really long if/else
construct.
Just to summarize the thread to date on this: Switching on an enum
*is* faster than switching on a string. (The compiler may use a vector
table; even if it just uses a series of comparisons, the comparisons
are cheaper.) However, converting the string to an enum more than
wipes out the dispatch gains, and is only worthwhile if you can use
the enum several times.
Now I have tried a dictionary of delegate methods. I really have no idea of
performance issues, but the code _appears_ cleaner in my class, due to the
fact that I don't have a huge if/else. I do however have a large constructor
where I initialise the dictionary... still, it was also the first time I
ever looked at delegates, so I consider it a learning experience.
I was thinking about this thread last night, and was going to suggest
a Dictionary.

For the three terms you initially showed, a Dictionary is probably
going to be slower than a switch - there's a certain amount of
overhead in computing commandString.GetHashCode() and traversing the
buckets. By fifteen terms, the Dictionary should be competitive, and
may even be faster; certainly the Dictionary will hold up better as
the app evolves and adds more commands.

Dictionary dispatch is much smaller and clearer than the big switch
statement. Of course, as you've found, you've simply moved the
complexity into the code that populates the Dictionary. However, you
can 'distribute' the code that populates the Dictionary, which reduces
the clutter and makes it easier to maintain as you add commands.

* If command handling is spread over multiple subsystems, you can have
each subsystem 'register' handlers when the subsystem is initialized.
That is, each subsystem's constructor would register its own
delegates.

* If all the command handling is done (or at least initiated) in
methods of the dispatching class, you can use custom attributes to
mark command handling methods. Instead of a long series of
`Dispatch["control"] = ControlHandler;` statements, you'd decorate the
ControlHandler method with an attribute like
`[CommandHandler("control")]`, and your Dictionary population code
would just look for methods with the CommandHandler attribute, and get
the command string from the attribute. The Dictionary population code
is more complex, but it's smaller and doesn't have to be modified when
you add a new command; you just add the command handler and the
attribute ensures registration.

--

..NET 2.0 for Delphi Programmers
www.midnightbeach.com/.net
What you need to know.
Nov 30 '06 #12

This discussion thread is closed

Replies have been disabled for this discussion.