Using properties in switch statement cases? - c#

I have a switch statement in one class that generates Command objects, based on if a certain line in a code file matches the particular code for that Command object.
like this:
switch (line):
{
case "#CODE1":
return new Command1();
case "#CODE2":
return new Command2();
}
I want to turn it into something like this:
switch (line):
{
case Command1.Code:
return new Command1();
case Command2.Code:
return new Command2();
}
I tried it by creating a public static property of Command1, but the compiler complains...
Is there a way to do something along this intent, that the compiler won't complain about?

I think you can do this only with constants... so if it's possible for you, use constant fields instead of public static properties. The difference is that it's treated like a literal at compile time, so if the value changes, you would need to recompile all assemblies that reference the constant.

Switch only works on numeric types and string types, not properties. You can try defining a public string constant on your Command1 and Command2 class, which you should be able to switch on instead.
public class Command1
{
public string const Code = "#CODE1";
}

since you are working with strings I'm not sure if it's the best approach, but using enums works for me
enum CommandEnum { CommandOne, ComandTwo, CommandN }
//...
CommandEnum myCommand;
//...
switch (myCommand)
{
case myCommand.CommandOne:
return new Command1();
case myCommand.CommandTwo:
return new Command2();
//...
}

You could always fall back on the tried and true if / else block
if (line == Command1.Code)
return new Command1();
else if (line == Command2.Code)
return new Command2();
That's not so evil, is it?

I think your problem is you need to instantiate your objects before you can determine their property values.
I'm assuming you have a code file with tokenized instructions, like:
#CODE1
#CODE2
and you want a class to read each line of your file and then perform whichever instructions the tokens define.
You got it to work, but instead of doing a direct string comparison to the token in the file, you want the value of the token stored in a property of your objects? The problem with that approach is you have to create a new instance of your object (commands 1 and 2) before you can refer to their property values.
If I understand what you've done and what you want to do, I think your solution was fine the way it was. I'm not 100% sure I really understand what you want to do, though, or why.
HTH

If you want to check against properties on a class. I'm assuming that you probably want to be able to change those properties and check accordingly. You'll have to use an if, else if, else if type statement.
If you've got a jones to use a switch statement, you're SOL unless you're checking an integral type against constant values. if, else if, else if blocks are ugly, but it'll do what you're looking for.

Related

How do you return different lists based on an enum?

I've seen that people have asked similar questions but they're normally using complex types and resolve to use interfaces instead. What I would like to do is pass back either list, list or list depending on an enum. Something like this:
private IList<T> GetValueFromType<T>(MyData data)
{
switch (data.SomeType)
{
case MyType.Percent:
var PercentValues = new List<double>();
PercentValues.Add(data.CompAPercentage);
PercentValues.Add(data.CompBPercentage);
return (T)PercentValues;
case MyType.Money:
var MoneyValues = new List<decimal>();
MoneyValues.Add(data.CompAMoney);
MoneyValues.Add(data.CompBMoney);
return (T)MoneyValues;
case MyType.Months:
var MonthValues = new List<int>();
MonthValues.Add(data.CompAMonth);
MonthValues.Add(data.CompBMonth);
return (T)MonthValues;
}
}
This shows an error on all 3 return statements saying the type can't be converted to 'T'. Is this possible / advised or is this a code smell?
You basically can't do this.
It is possible to circumvent the static type-checking as Mike's answer says in order to make GetValueFromType<T> compile, but how will you invoke it? Your calling code will need to specify T, eg.
var myValue = GetValueFromType<int>(myData)
because there's no way to infer T from the call itself, and when the method tries to return a list which doesn't match your choice of T you'll get an InvalidCastException. Given that you need to interrogate MyData to find out how to call this method safely, you might as well have the switch in the calling code.
This is somewhat dangerous because it loses some of the power of static type checking and is easy for callers to get wrong. The compiler will flag it. You may need to insert an (object) cast to tell the compiler you really want to make the cast:
return (IList<T>) (object) MonthValues;

Use dynamic keys in keydownevent

I'm doing a little C# program, but it is configurable. Properties.Settings.Default.foobar is equal to F3, but that is subject to change. Originally it'd be this way:
case Keys.F3:
//dostuff
break;
But I need Properties.Settings.Default.foobar in place of F3, since it's a setting and thus subject to change.
case Keys.Properties.Settings.Default.foobar:
Obviously doesn't work, nor does putting it in parenthesis, so I'm not sure. I'm clearly new to C#, so any help?
The program uses unfocused hotkeys, but these keys are user configurable, so I can't have any sort of constant/static for a case, right?
case Keys.Properties.Settings.Default.foobar:
As you say, this obviously doesn't work. The specific reason is that the values for a case statement must be compile-time constants.
A simpler if comparison would probably be better. Since your value is a Keys and your property is a string, you'll need to convert one type to the other for comparison. I'll convert to a string for simplicity, or you could convert the string to the enum type.
if (myVar.ToString() == Properties.Settings.Default.foobar)
So instead of having, e.g.
switch (myVar) {
case Keys.F1:
// something
case Keys.F2:
// something
}
You would have:
if (myVar.ToString() == Properties.Settings.Default.foo) {
// something
} else if (myVar.ToString() == Properties.Settings.Default.bar) {
// something
}
Keys.F3 is a value of the Keys enumeration. So you'll need to convert your Properties.Settings.Default.foobar string into a value of the enumeration too.
Luckily, there is a built-in method to do that:
var foobarKey = (Keys)Enum.Parse(typeof(Keys), Properties.Settings.Default.foobar);
...
if (whatever == foobarKey)
{
...

Enum.Parse() or Switch

For converting a string to an enum, which of the following ways is better?
This code:
colorEnum color = (colorEnum)Enum.Parse(typeof(colorEnum), "Green");
or this:
string colorString = ...
colorEnum color;
switch (colorString)
{
case "Green":
color = colorEnum.Green;
break;
case "Red":
color = colorEnum.Red;
break;
case "Orange":
color = colorEnum.Orange;
break;
....
}
You should use the Enum.TryParse, if it fails you can handle the error correctly.
sample:
ColorsEnum colorValue;
if (Enum.TryParse(colorString, out colorValue))
if (Enum.IsDefined(typeof(Colors), colorValue) | colorValue.ToString().Contains(","))
Console.WriteLine("Converted '{0}' to {1}.", colorString, colorValue.ToString());
else
Console.WriteLine("{0} is not an underlying value of the Colors enumeration.", colorString);
else
Console.WriteLine("{0} is not a member of the Colors enumeration.", colorString);
(Warning: includes plug for my own open source library...)
Personally I'd use Unconstrained Melody, which ends up with cleaner and more typesafe code:
ColorEnum color = Enums.ParseName<ColorEnum>(text);
You can use TryParseName if you suspect it may be invalid. Obviously this requires an extra library, but hopefully you'll find other things in there helpful too :)
Enum.TryParse from .NET 4 is better than the other built-in options, but:
You won't catch non-enum types at compile time, e.g. Enum.TryParse<int>(...) will still compile; Unconstrained Melody really only allows enum types
Enum.TryParse will also parse "1" (or whatever the numeric value is when converted to a string) - if you really only expect names, I think it's better to only accept names
I definitely wouldn't switch on the string values - it means if you rename the enum values, you've got to remember to rename the case value as well.
And what about Enum.TryParse<TEnum> ?
string myColorStr = "red";
colorEnum myColor;
if(!Enum.TryParse<colorEnum>(myColorStr, true, out myColor))
{
throw new InvalidOperationException("Unknown color " + myColorStr);
}
Number 1 simply on readability and maintainability. If you extend the enum you need to do no extra work, wheras with 2 you have to add more cases to the switch statement
Because you added the tag 'performance', I'm going to go with the switch.
Yes, you will have to change the cases when you rename/add/remove anything in the enum. Well that's just too bad then. Any variant of Enum.Parse/TryParse uses a lot of weird code and some reflection, just take a look inside the function with ILSpy or such. Then there is also the issue of accepting "-12354" and even a comma-separated list of valid names (resulting in all of them ORed together) even when the enum doesn't have a [Flags] attribute.
As an alternative, you could make a dictionary that translates enum names to values. It should actually be faster than the switch, because a switch on strings also goes through a dictionary but you save the actual switch part.
Obviously both ways cost some more maintenance than enum.parse and variants; whether it's worth it is up to you, since out of all of us only you have enough knowledge of the project to make the performance/coding-time trade off.
1) Is much better. It's cleaner code. You are doing in one line what would take multiple in 2). Also, it's less bug prone. When you add another item to colorEnum, you would need to remember to extend 2) wheras 1) would just work.
You may also want some error handling on the Enum.Parse.
Other than the fact that the two different code snippets doesn't do the same thing, I'd use this:
colorEnum color;
if (!colorEnum.TryParse(colorString, true, out color)
color = colorEnum.Green; // Or whatever default value you wish to have.
If you don't have .NET 4.0 then I'd do something like this:
public static TEnum ToEnum<TEnum>(this string strEnumValue, TEnum defaultValue)
{
if (!Enum.IsDefined(typeof(TEnum), strEnumValue))
return defaultValue;
return (TEnum)Enum.Parse(typeof(TEnum), strEnumValue);
}
This is an Extension Method to string.
Personally, while I am totally fine with the Enum.Parse solution for non-performance scenarios (read: one off run of this function occasionally ... and there are many such scenarios to be sure), I can't countenance the thought of possibly involving some reflection type method when this function needs to be performed in a loop over hundreds/thousands plus enum values at once. Gack!
So the following is a solution that gets some of the best of both worlds.
Just retrieve all values of the enum at startup time or what not, whenever it works best for you (below is one way of doing that), and then construct a Dictionary with them.
private static Dictionary<string, Color> colorDictionary;
public static Dictionary<string, Color> ColorDictionary
{
get
{
if (colorDictionary== null) {
colorDictionary = new Dictionary<string, Color>();
var all = Enum.GetValues(typeof(Color)).OfType<Color>();
foreach (var val in all)
dict.Add(val.ToString(), val);
}
return colorDictionary;
}
}
I find the switch variant horrible since you will have to modify the switch everytime you change the enum also.
I like to use the TryParse that belongs to your enum. So you can use it like this
string colorString = .....
colorEnum color;
colorEnum.TryParse(colorString, out color);
Or if you don't care about the case of the string
colorEnum.TryParse(colorString, true, out color);
The returnvalue of TryParse is true if the string was a valid enum, false if not.
On a performance point of view, as enums are implemented as static fields, the parse method will probably ends up doing refection on then enum type and try a GetField method which might be faster than the case. On the other end, if 90% of the case, the color is green, the case will be very fast... Note that the CLR sometimes rearrange code internally, changing the order of the case based on statistic (actually, I'm not sure it does that but the doc claims it could).
I use the following, it gets you all the type safety while still not falling over when you add new values into the Enum, it's also very fast.
public static colorEnum? GetColorFromString(string colorString)
{
colorEnum? retVal = null;
if(Enum.IsDefined(typeof(colorEnum), colorString))
retVal = (colorEnum)Enum.Parse(typeof(colorEnum), colorString);
return retVal;
}
My test with 8 items in the enum shows this way to be faster than the switch method.
Or else you can use (the very slow way):
public static colorEnum? GetColorFromString(string colorString)
{
foreach (colorEnum col in Enum.GetValues(typeof(colorEnum)))
{
if (col.ToString().Equals(colorString))
{
return col;
}
}
return null;
}

Converting code using generics

I've following code that uses the passed Object and acts on it after determining its type. My question is that if I convert it to use generics, will I get any performance advantage since I'd still have to determine the type of T before I act upon it? Will I save ticks on boxing/unboxing?
private void BindOptionFields(Object obj, String selectedValue, int dataLanguageID)
{
String typ = obj.GetType().Name;
switch(typ.ToLower())
{
case "ratingscaleitem":
SetRatingScale((Common.RatingScaleItem)obj, dataLanguageID, selectedValue);
break;
case "taskstatus":
text = ((TaskStatus)obj).TaskName;
optionValue = ((TaskStatus)obj).StateID.ToString();
break;
case "planlite":
text = ((XYZ.ABC.PlanLite)obj).PlanName;
optionValue = ((XYZ.ABC.PlanLite)obj).Id.ToString();
break;
case "datarow":
text = ((DataRow)obj)["TextColumn"].ToString();
optionValue = ((DataRow)obj)["KeyColumn"].ToString();
break;
default:
break;
}
if (optionValue == selectedValue)
{
selected = true;
}
}
Note: I've 3 constructors in my class that receive an ArrayList of 20 different types (similar types in ArrayList for a particular call). I loop through the arraylist and call this BindOptionFields() so if I've to write overloaded methods, I'll have to overload my constructors for 20 cases each. Can someone suggest a less tedious solution that would be fast as well?
You're misunderstanding generics.
If you convert this method to a generic method, the caller will need to specify the generic parameter at compile-time.
At that point, you can just use a normal set of overloaded methods.
Would it not be better to add a BindOptionField method (perhaps as part of an Interface e.g. IOptionFieldBindable) to the types you're switching on here?
The TaskStatus, PlanLite, and DataRow Types are good candidates particularly, since they're each providing a different way to set the same two values. That way, you could just call
(obj as IOptionFieldBindable).BindOptionField(text, optionValue);
Your solution would also be less Stringly Typed :)

which is better, using a nullable or a boolean return+out parameter

Lets say I have a function that needs to return some integer value. but it can also fail, and I need to know when it does.
Which is the better way?
public int? DoSomethingWonderful()
or
public bool DoSomethingWonderful(out int parameter)
this is probably more of a style question, but I'm still curious which option people would take.
Edit: clarification, this code talks to a black box (lets call it a cloud. no, a black box. no, wait. cloud. yes). I dont care why it failed. I would just need to know if I have a valid value or not.
I like the nullable version better, because you can use the null coalesce operator ?? on it, e.g.:
int reallyTerrible = 0;
var mightBeWonderful = DoSomethingWonderful() ?? reallyTerrible;
It depends on how you think the calling code should look like. And therefore what your function is used for.
Generally, you should avoid out arguments. On the other hand, it could be nice to have code like this:
int parameter;
if (DoSomething(out paramameter))
{
// use parameter
}
When you have a nullable int, it would look like this:
int? result = DoSomething();
if (result != null)
{
// use result
}
This is somewhat better because you don't have an out argument, but the code that decides if the function succeeded doesn't look very obvious.
Don't forget that there is another option: use Exeptions. Only do this if the case where your function fails is really an exceptional and kind of a error-case.
try
{
// normal case
int result = DoSomething()
}
catch (SomethingFailedException ex)
{
// exceptional case
}
One advantage of the exception is that you can't just ignore it. The normal case is also straight forward to implement. If the exceptional case something you could ignore, you shouldn't use exceptions.
Edit: Forgot to mention: another advantage of an Exception is that you also can provide information why the operation failed. This information is provided by the Exception type, properties of the Exception and the message text.
Why not throw an exception?
I would follow the pattern used in some place in the .Net library like:
bool int.TryParse(string s, out value)
bool Dictionary.TryGetValue(T1 key, out T2 value)
So I would say:
public bool TryDoSomethingWonderful(out int parameter)
It really depends on what you are doing.
Is null a meaningful answer? If not, I would prefer a bool TryDoSomethingWonderful(out int) method call. This matches up with the Framework.
If, however, null is a meaningful return value, returning int? makes sense.
Unless performance is the primary concern you should return an int and throw an exception on failure.
I would use the second, because I probably need to know right away if the call succeeded, and in that case I would rather write
int x;
if( DoSomethingWonderful( out x ) )
{
SomethingElse(x);
}
than
int? x = DoSomethingWonderful();
if( x.HasValue )
{
SomethingElse(x.Value);
}
I am in favor of using an output parameter. In my opinion, this is the kind of situation for which use of an output parameters is most suited.
Yes, you can use the coalesce operator to keep your code as a one-liner if and only if you have an alternative value that you can use in the rest of your code. I often find that is not the case for me, and I would prefer to execute a different code path than I would if I was successfully able to retrieve a value.
int value;
if(DoSomethingWonderful(out value))
{
// continue on your merry way
}
else
{
// oops
Log("Unable to do something wonderful");
if (DoSomethingTerrible(out value))
{
// continue on your not-so-merry way
}
else
{
GiveUp();
}
}
Additionally, if the value that I want to retrieve is actually nullable, then using a function with an output parameter and a boolean return value is, in my opinion, the easiest way to tell the difference between "I was unsuccessful in retrieving the value" and "The value I retrieved is null". Sometimes I care about that distinction, such as in the following example:
private int? _Value;
private bool _ValueCanBeUsed = false;
public int? Value
{
get { return this._Value; }
set
{
this._Value = value;
this._ValueCanBeUsed = true;
}
}
public bool DoSomethingTerrible(out int? value)
{
if (this._ValueCanBeUsed)
{
value = this._Value;
// prevent others from using this value until it has been set again
this._ValueCanBeUsed = false;
return true;
}
else
{
value = null;
return false;
}
}
In my opinion, the only reason most people tend not to use output parameters is because they find the syntax cumbersome. However, I really feel that using output parameters is the more appropriate solution to this problem, and I found that once I got used to it I found the syntax much preferable to returning a null value.
If there's only one way it can fail, or if you'll never need to know why it failed, I'd say it's probably simpler and easier to go with the nullable return value.
Conversely, if there are multiple ways it could fail, and the calling code could want to know exactly why it failed, then go with the out parameter and return an error code instead of a bool (alternatively, you could throw an exception, but based on your question, it seems you've already decided not to throw an exception).
You should rather then use a try catch. This seems like the caller does not know what might happen?
Should we check both bool and the out, or should i check both returns null and the actual return.
Let the method do what it should, and in the case where it failed, let the caller know that it failed, and the caller hanlde as requied.
Interestingly enough, my personal opinion sways significantly based on the nature of the method. Specifically, if the method's purpose is to retrieve a single value, as opposing to "doing something".
Ex:
bool GetSerialNumber(out string serialNumber)
vs
string GetSerialNumber() // returns null on failure
The second feels more "natural" to me somehow, and likewise:
bool GetDeviceId(out int id)
vs
int? GetDeviceId() // returns null on failure`
But I admit this really falls into "coding style" territory.
Oh, and I, too, would tend to favor exception throwing:
int GetDeviceId() // throws an exception on read failure
I'm still not sold on why they'd be so wrong. Can we have a thread on that, Oren? ;-)
I dislike Microsoft's "Try" pattern in which the "out" parameter is used to return a data item. Among other things, methods coded in that fashion cannot be used in covariant interfaces. I would rather see a method coded as: T GetValue(out bool Successful) or perhaps T GetValue(out GetValueErrorEnum result); or T GetValue(out GetValueErrorInfo result); if something beyond a true/false might be needed. Since every data type has a legal default value, there's no problem with deciding what to return if the function fails. Calling code can easily say:
bool success;
var myValue = Thing.GetValue(ref success);
if (success)
.. do something using myValue
else
.. ignore myValue
It would be nice if .net and C# offered true covariant 'copy out' parameters (the caller would allocate space for the result, pass a pointer to that space to the called function, and then copy the allocated space to the passed-in variable only after the function returned).

Categories

Resources