Related
I would like to have a C# method which counts the number of cases in a switch statment. (Let's call it CaseCounter). For example, let's say you have this enum and these two methods:
enum Painter
{
Rubens,
Rembrandt,
Vermeer,
Picasso,
Kandinsky
}
int GetYearOfBirth(Painter painter)
{
switch(painter)
{
case Painter.Kandinsky:
return 1866;
case Painter.Picasso:
return 1881;
case Painter.Rembrandt:
return 1606;
case Painter.Rubens:
return 1577;
case Painter.Vermeer:
return 1632;
default:
return 0;
}
}
bool IsModern(Painter painter)
{
switch (painter)
{
case Painter.Kandinsky:
case Painter.Picasso:
return true;
default:
return false;
}
}
Now the following equalities should hold:
CaseCounter("GetYearOfBirth") == 5
CaseCounter("IsModern") == 2
(It is not important whether or not you include the default case in the count. Also, the parameter to CaseCounter doesn't need to be a string; any type which can somehow be used to represent a method will do.)
So, how would you go about implementing CaseCounter? Is it even possible?
--- ADDENDUM (EDIT) ---
Here's a bit of background info in case you're wondering why I asked this question.
I'm maintaining a code base which contains a lot of methods that switch on enums. The methods are spread across various classes; this makes life difficult when an enum is extended (for example, when you add a new Painter). To make maintenance a little bit easier, I have written some unit tests of the following form:
// If this test fails please check that the following methods are still OK:
// MyClass.GetYearOfBirth, MyOtherClass.IsModernAllCases .
// (There is no guarantee that the above list is up-to-date or complete.)
[Test]
public void PainterCountTest()
{
int numberOfMembers = Enum.GetValues(typeof(NotificationID)).Length;
Assert.AreEqual(5, numberOfMembers);
}
(In this example, IsModernAllCases is just a variation of IsModern which refers explicitly to all 5 possible values of the Painter enum.)
This test is better than nothing, but it's clumsy. It would be a little less clumsy if you could write something like this:
[Test]
public void PainterCountTest()
{
int numberOfMembers = Enum.GetValues(typeof(NotificationID)).Length;
int numberOfCases_getYearOfBirth = CaseCounter("MyClass.GetYearOfBirth");
Assert.AreEqual(numberOfCases_getYearOfBirth, numberOfMembers);
int numberOfCases_modern = CaseCounter("MyOtherClass.IsModernAllCases");
Assert.AreEqual(numberOfCases_modern, numberOfMembers);
}
In this scenario, at least you don't have to modify the unit test when you extend the enum.
It should be possible to do with the Roslyn CTP - Microsoft's compiler-as-a-service pre-release product. It has API's to let you inspect C# code and represent it as a tree of instructions. Unfortunately, it is a CTP, which may or may not be a problem for you - just remember it is pre-release software if you try to use it.
If you can't use Roslyn, I think the only way would be to inspect the generated IL. A daunting task, to say the least. I haven't got any sample code for that, but if you want to try it - I would start by looking at the Cecil Mono project, which has some API's for inspecting IL.
You could also MethodInfo.GetMethodBody to get the raw IL bytes and then parse those bytes yourself, but it does require some work to do that.
Also, see this related question.
This can't be done via Reflection, but could be done via the Roslyn CTP. Roslyn provides the tooling required to analyze the source code itself, and determine information about it. You could walk the trees in this code to find the methods containing switch statements, and make a count of individual cases.
Without knowing why you are doing this, it's tough to know if this will be an acceptable approach for you.
Since these C# files are basically just text files on your computer, you could create a separate application that loops through all the files. It would need to recognize methods, count the number of occurrences of case words (that aren't comments), and report the results.
Now, if you need this functionality to run at runtime, within your app, then this approach won't work.
make a find search in visual studio on your case word it is enough to make your refactoring
I have written an application in C# which at present includes nearly 400 mathematical functions, each with its own integer ID. To access function code, my application currently feeds the function's ID to a huge 'switch' block which has one 'case' block per function: total, nearly 400 'case' blocks. This seems to work seamlessly and quite fast, but is there a more efficient way of matching code blocks to function identifiers?
Sounds like you want a Dictionary<string, Func<double, double>> or something similar...
// Better, use an *enum* of function IDs...
private static readonly Dictionary<int, Func<double, double>> Functions =
new Dictionary<int, Func<double, double>>
{
{ 0, Math.Sqrt },
{ 100, x => x * 2 },
...
};
Note that just as this refers to Math.Sqrt, it could also refer to your own methods - you don't have to put all the logic in the collection initializer. I would probably break any function which wasn't just a single expression into a method.
You'd then apply it like this:
public void Apply(int functionId, double value)
{
Func<double, double> function;
if (!Functions.TryGetValue(functionId, out function))
{
// Throw an exception or whatever
}
return function(value);
}
Note that I've used a dictionary here to be general purpose; if the function IDs are 0...n, you could use an array instead.
As noted in the comment at the start, it would be neater to use an enum of function IDs than just integers.
A better solution would be to encapsulate each function in its own class and then use the strategy pattern to swap in the function required.
Having each function in its own class has the advantage that it is simpler to see the code for the function in one place and maintains good separation of concerns, with each class only responsible for the code to implement that function. It will make testing those functions easier as well.
It also would mean that adding functions in the future could be more flexible, as you would have the opportunity of adding functions from external sources without having to recompile.
Another benefit of this approach could be that as the functions would all implement an interface, you could scan your assemblies for those implementations at load time and thus automatically have new functions added to the list of available functions without any extra effort.
As far as I know switch statements that contain more than a few items are already optimized by the compiler to use a lookup table internally so the performance gain by switching to e.g. a Dictionary should be minimal. As always though, you should measure both approaches to make a decision.
Further re the potential for using Dictionary, this fellow observes that having six or more string cases and a default case resulted in the compiler generating a Dictionary. So, why not just skip that conversion during compilation?
It sounds like you are writing your code like this (psudocode):
function doMath(a,b, functionID) {
switch (functionID) {
case 1:
// addition function
return a + b;
break;
case 2:
// subtraction function
return a - b;
break;
}
}
when you want to write it like this:
function add(a,b) {
return a + b;
}
function subtract(a,b) {
return a - b;
}
or am I misunderstanding your requirements?
This questions is a follow-up to my previous post here. Martinho has asked me to provide more information regarding my system. He has suggestion that there might be a better way to achieve what I am attempting. So, if there is a question here, I guess I am wondering if this is poor design? If so, what can be improved and how (I learn best from illustrations). Thanks.
I am designing middleware for an iPhone application at work.
Rather than explicitly calling various objects from the client, the developers want to use generics where a "Group" returns a JSON string based on a passed-in parameter. The parameter represents the first screen a user sees when he logs in. We are calling the login screen the "Dashboard".
So, when the client calls the server method:
Contracts.GroupDto IDashboardService.GetGroupById(string groupId)
{
var obj = GroupRepository.GetGroupById(groupId);
return new Contracts.GroupDto
{
...
};
}
The server uses the GroupRepository method GetGroupById to return a generic object type:
public static IList<G> GetGroupById<G>(int groupId)
{
DashboardGroupType type = (DashboardGroupType)groupId;
IList<G> result = new List<G>();
var obj = default(G);
switch (type)
{
case DashboardGroupType.Countries:
break;
case DashboardGroupType.Customers:
// this returns a list of typ IEnumerable<Customer>
obj = (G) CustomerRepository.GetAllCustomers();
break;
case DashboardGroupType.Facilities:
// this returns a list of typ IEnumerable<Facility>
obj = (G) FacilityRepository.GetAllFacilities();
break;
case DashboardGroupType.Heiarchy:
break;
case DashboardGroupType.Lines:
break;
case DashboardGroupType.Regions:
// this returns a list of typ IEnumerable<string>
obj = (G) CustomerRepository.GetRegionsHavingCustomers();
break;
case DashboardGroupType.States:
// // this returns a list of typ IEnumerable<Customer>
obj = (G) CustomerRepository.GetStatesHavingCustomers();
break;
case DashboardGroupType.Tanks:
break;
default:
break;
}
result.Add(obj);
return result;
}
The object type returned is based on the parameter passed in to GetGroupById. For example, if the value is 1, the method looks at the DashboardGroupType enum:
and passes the parameter of 1, the server looks at the following enum:
public enum DashboardGroupType
{
Countries = 0,
Regions = 1,
Customers = 2,
Facilities = 3,
Lines = 4,
Tanks = 5,
States = 6,
Heiarchy = 7
}
and returns a list of regions of type IEnumerable to the calling client.
Any thoughts regarding this design (especially regarding the IList GetGroupById(int groupId) method? If you have suggestions, I would appreciate an illustration of your improvement.
Thanks in advance.
That code doesn't make a lot of sense to me. Your generic returns an IList<G>, but the list only ever has a single item added to it. And sometimes that item is null (or default<G>, which will be null when G is a reference type).
I can't imagine why the developers would favor a GetGroupById generic method when doing so is more complicated than having separate methods. That is, why not have GetFacilities, GetCustomers, etc?
Perhaps they prefer having a single service method that returns JSON to them. If there's some compelling reason to do that (although I can't imagine one, other than developer laziness), then I would suggest that you do the switch in that method and not mess with the generic. That is:
Contracts.GroupDto IDashboardService.GetGroupById(string groupId)
{
switch ((DashboardGroupType)groupId)
{
case DashboardGroupType.Regions:
// Get the Regions list, convert to JSON, and return.
break;
// do the same kind of thing for the other group types.
}
}
Adding the generic method in this case is just needless complexity--it does nothing to simplify or increase understanding of the code. To the contrary, it makes the code harder to understand.
In general, if you have code in a generic method that acts differently based on the type parameter, then it's a very good indication that your generic method isn't really generic and probably should be implemented some other way.
Do not use switch statement. It may introduce bugs and hard to maintain.
I suggest you to create a base class (abstract) with default behavior for GetGroupById() and derive classes for each of the groups DashboardGroupType.
Enum are appropriate when you just need to store as a variable/property and don't have to do perform any logic based on the value.
In your derived classes you can override the default behavior or keep it to default (return null). You may think of using null object design pattern as well.
You will appreciate the design when some change comes up and change is the only constant :)
You can refer to Martin Fowler's book on" Refactoring"
I'm reading up on core C# programming constructs and having a hard time wrapping my head around the out parameter modifier. I know what it does by reading but am trying to think of a scenerio when I would use it.
Can someone give me a real-world example? Thanks.
The main motivation to using an out parameter is to allow a function to return multiple values to the caller and everyone else provided examples in the framework. I'll take a different approach to answering your question by exploring the reasoning behind having out parameters in the first place. I won't write out actual examples but describe them.
Normally you have only one mechanism to return values, the function's return value. Sure you could use a global (static) or instance variables too but that's not very practical nor safe to do in general (for reasons I won't explain here). Prior to .NET 3.5, there wasn't a really practical way to return multiple values from a function. If out or ref modifiers were not available, you would have a few options:
If all your values had the same type, you could return some collection of the values. This is perfectly fine in most cases, you could return an array of number, list of strings, whatever. This is perfect if all the values were related in exactly the same way. i.e., All numbers were the number of items in a container, or the list was of names of guests at a party. But what if the values you returned represented different quantities? What if they had different types? A list of objects could hold them all but it is not a very intuitive way to manipulate that sort of data.
For the case when you need to return multiple values of different types, the only practical option you had was to create a new class/struct type to encapsulate all these values and return an instance of that type. Doing so you could return strongly typed values with intuitive names and you could return multiple values this way. The problem is that in order to get that, you had to define the type with a specific name and everything just to be able to return multiple values. What if you wanted to return only two values which were simple enough making it impractical to create a type for it? You have a couple more options again:
You could create a set of generic types to contain a fixed amount of values of varying types (like a tuple in functional languages). But it is not as appealing to do so in a reusable manner since it wasn't part of the framework at the time. It could be put in a library but now you add a dependency on that library just for the sake of these simple types. (just be glad that .NET 4.0 now includes the Tuple type) But this still doesn't solve the fact that these are simple values which means added complexity for a simple task.
The option that was used was to include an out modifier which allows the caller to pass a "reference" to a variable so that the function may set the referenced variable as another way to return a value. This way of returning values was also available in C and C++ in many ways for the same reasons and played a role in influencing this decision. However the difference in C# is that for an out parameter, the function must set the value to something. If it doesn't, it results in a compiler error. This makes this less error prone since by having an out parameter, you're promising the caller that you will set the value to something and they can use it, the compiler makes sure you stick to that promise.
A note on the typical usage of the out (or ref) modifier, it will be rare to see more than one or two out parameters. In those cases, it will almost always be a much better idea to create the encapsulating type. You would typically use it if you needed just one more value to return.
However since C#-3.0/.NET-3.5 with the introduction of anonymous types and tuples introduced in .NET 4.0, these options provided alternative methods to return multiple values of varying types easier (and more intuitive) to do.
there are many scenarios where you would use it, but the main one would be where your method needs to return more then one parameter. Take, for example, the TryParse methods on int type. In this case, instead of throwing an exception a bool is returned as a success/failure flag and the parsed int is return as the out param. if you were to call int.Parse(...) you could potentially throw an exception.
string str = "123456";
int val;
if ( !int.TryParse(str,out val) )
{
// do some error handling, notify user, etc.
}
Sure, take a look at any of the TryParse methods, such as int.TryParse:
The idea is you actually want two pieces of information: whether a parse operation was successful (the return value), and, if so, what the result of it actually was (the out parameter).
Usage:
string input = Console.ReadLine();
int value;
// First we check the return value, which is a bool
// indicating success or failure.
if (int.TryParse(input, out value))
{
// On success, we also use the value that was parsed.
Console.WriteLine(
"You entered the number {0}, which is {1}.",
value,
value % 2 == 0 ? "even" : "odd"
);
}
else
{
// Generally, on failure, the value of an out parameter
// will simply be the default value for the parameter's
// type (e.g., default(int) == 0). In this scenario you
// aren't expected to use it.
Console.WriteLine(
"You entered '{0}', which is not a valid integer.",
input
);
}
Many developers complain of out parameters as a "code smell"; but they can be by far the most appropriate choice in many scenarios. One very important modern example would be multithreaded code; often an out parameter is necessary to permit "atomic" operations where a return value would not suffice.
Consider for example Monitor.TryEnter(object, ref bool), which acquires a lock and sets a bool atomically, something that wouldn't be possible via a return value alone since the lock acquisition would necessarily happen before the return value were assigned to a bool variable. (Yes, technically ref and out are not the same; but they're very close).
Another good example would be some of the methods available to the collection classes in the System.Collections.Concurrent namespace new to .NET 4.0; these provide similarly thread-safe operations such as ConcurrentQueue<T>.TryDequeue(out T) and ConcurrentDictionary<TKey, TValue>.TryRemove(TKey, out TValue).
Output parameters are found all over the .NET framework. Some of the uses I see most often are the TryParse methods, which return a boolean (indicating whether or not the parse was valid) and the actual result is returned via the output parameter. While it's also very common place to use a class when you need to return multiple values, in such an example as this it's a little heavy handed. For more on output parameters, see Jon Skeet's article on Parameter passing in C#.
Simple, when you have a method that returns more than one value.
One of the most "famous" cases is Dictionary.TryGetValue:
string value = "";
if (openWith.TryGetValue("tif", out value))
{
Console.WriteLine("For key = \"tif\", value = {0}.", value);
}
else
{
Console.WriteLine("Key = \"tif\" is not found.");
}
As others have said - out parameters allow us to return more than one value from a method call without having to wrap the results in struct/class.
The addition of the xxx.TryParse methods greatly simplified the coding necessary to convert between a string value (frequently from the UI) and a primitive type.
An example of what you might have had to write to achieve the same functionality is here:
/// <summary>
/// Example code for how <see cref="int.TryParse(string,out int)"/> might be implemented.
/// </summary>
/// <param name="integerString">A string to convert to an integer.</param>
/// <param name="result">The result of the parse if the operation was successful.</param>
/// <returns>true if the <paramref name="integerString"/> parameter was successfully
/// parsed into the <paramref name="result"/> integer; false otherwise.</returns>
public bool TryParse(string integerString, out int result)
{
try
{
result = int.Parse(integerString);
return true;
}
catch (OverflowException)
{
// Handle a number that was correctly formatted but
// too large to fit into an Int32.
}
catch (FormatException)
{
// Handle a number that was incorrectly formatted
// and so could not be converted to an Int32.
}
result = 0; // Default.
return false;
}
The two exception checks that are avoided here make the calling code much more readable. I believe that the actual .NET implementations avoid the exceptions altogether so perform better as well. Similarly, this example shows how IDictionary.TryGetValue(...) makes code simpler and more efficient:
private readonly IDictionary<string,int> mDictionary = new Dictionary<string, int>();
public void IncrementCounter(string counterKey)
{
if(mDictionary.ContainsKey(counterKey))
{
int existingCount = mDictionary[counterKey];
mDictionary[counterKey] = existingCount + 1;
}
else
{
mDictionary.Add(counterKey, 1);
}
}
public void TryIncrementCounter(string counterKey)
{
int existingCount;
if (mDictionary.TryGetValue(counterKey, out existingCount))
{
mDictionary[counterKey] = existingCount + 1;
}
else
{
mDictionary.Add(counterKey, 1);
}
}
And all thanks to the out parameter.
bool Int32.TryParse(String, out Int);
or something similar like Dictionary.TryGetValue.
But I would consider this one to be a not too good practice to employ it, of course, using those provided by API like the Int32 one to avoid Try-Catch is exceptions.
//out key word is used in function instead of return. we can use multiple parameters by using out key word
public void outKeyword(out string Firstname, out string SecondName)
{
Firstname = "Muhammad";
SecondName = "Ismail";
}
//on button click Event
protected void btnOutKeyword_Click(object sender, EventArgs e)
{
string first, second;
outKeyword(out first, out second);
lblOutKeyword.Text = first + " " + second;
}
This question already has answers here:
Is Switch (Case) always wrong?
(8 answers)
Closed 9 years ago.
I've come across a switch statement in the codebase I'm working on and I'm trying to figure out how to replace it with something better since switch statements are considered a code smell. However, having read through several posts on stackoverflow about replacing switch statements I can't seem to think of an effective way to replace this particular switch statement.
Its left me wondering if this particular switch statement is ok and if there are particular circumstances where switch statements are considered appropriate.
In my case the code (slightly obfuscated naturally) that I'm struggling with is like this:
private MyType DoSomething(IDataRecord reader)
{
var p = new MyType
{
Id = (int)reader[idIndex],
Name = (string)reader[nameIndex]
}
switch ((string) reader[discountTypeIndex])
{
case "A":
p.DiscountType = DiscountType.Discountable;
break;
case "B":
p.DiscountType = DiscountType.Loss;
break;
case "O":
p.DiscountType = DiscountType.Other;
break;
}
return p;
}
Can anyone suggest a way to eliminate this switch? Or is this an appropriate use of a switch? And if it is, are there other appropriate uses for switch statements? I'd really like to know where they are appropriate so I don't waste too much time trying to eliminate every switch statement I come across just because they are considered a smell in some circumstances.
Update: At the suggestion of Michael I did a bit of searching for duplication of this logic and discovered that someone had created logic in another class that effectively made the whole switch statement redundant. So in the context of this particular bit of code the switch statement was unnecessary. However, my question is more about the appropriateness of switch statements in code and whether we should always try to replace them whenever they are found so in this case I'm inclined to accept the answer that this switch statement is appropriate.
This is an appropriate use for a switch statment, as it makes the choices readable, and easy to add or subtract one.
See this link.
Switch statements (especially long ones) are considered bad, not because they are switch statements, but because their presence suggests a need to refactor.
The problem with switch statements is they create a bifurcation in your code (just like an if statement does). Each branch must be tested individually, and each branch within each branch and... well, you get the idea.
That said, the following article has some good practices on using switch statements:
http://elegantcode.com/2009/01/10/refactoring-a-switch-statement/
In the case of your code, the article in the above link suggests that, if you're performing this type of conversion from one enumeration to another, you should put your switch in its own method, and use return statements instead of the break statements. I've done this before, and the code looks much cleaner:
private DiscountType GetDiscountType(string discount)
{
switch (discount)
{
case "A": return DiscountType.Discountable;
case "B": return DiscountType.Loss;
case "O": return DiscountType.Other;
}
}
I think changing code for the sake of changing code is not best use of ones time. Changing code to make it [ more readable, faster, more efficient, etc, etc] makes sense. Don't change it merely because someone says you're doing something 'smelly'.
-Rick
This switch statement is fine. Do you guys not have any other bugs to attend to? lol
However, there is one thing I noticed... You shouldn't be using index ordinals on the IReader[] object indexer.... what if the column orders change? Try using field names i.e. reader["id"] and reader["name"]
In my opinion, it's not switch statements that are the smell, it's what's inside them. This switch statement is ok, to me, until it starts adding a couple of more cases. Then it may be worth creating a lookup table:
private static Dictionary<string, DiscountType> DiscountTypeLookup =
new Dictionary<string, DiscountType>(StringComparer.Ordinal)
{
{"A", DiscountType.Discountable},
{"B", DiscountType.Loss},
{"O", DiscountType.Other},
};
Depending on your point-of-view, this may be more or less readable.
Where things start getting smelly is if the contents of your case are more than a line or two.
Robert Harvey and Talljoe have provided excellent answers - what you have here is a mapping from a character code to an enumerated value. This is best expressed as a mapping where the details of the mapping are provided in one place, either in a map (as Talljoe suggests) or in a function that uses a switch statement (as suggested by Robert Harvey).
Both of those techniques are probably fine in this case, but I'd like to draw your attention to a design principal that may be useful here or in other similar cases. The the Open/Closed principal:
http://en.wikipedia.org/wiki/Open/closed_principle
http://www.objectmentor.com/resources/articles/ocp.pdf (make sure you read this!)
If the mapping is likely to change over time, or possibly be extended runtime (eg, through a plugin system or by reading the parts of the mapping from a database), then a using the Registry Pattern will help you adhere to the open/closed principal, in effect allowing the mapping to be extended without affecting any code that uses the mapping (as they say - open for extension, closed for modification).
I think this is a nice article on the Registry Pattern - see how the registry holds a mapping from some key to some value? In that way it's similar to your mapping expressed as a switch statement. Of course, in your case you will not be registering objects that all implement a common interface, but you should get the gist:
http://sinnema313.wordpress.com/2009/03/01/the-registry-pattern/
So, to answer the original question - the case statement is poor form as I expect the mapping from the character code to an enumerated value will be needed in multiple places in your application, so it should be factored out. The two answers I referenced give you good advice on how to do that - take your pick as to which you prefer. If, however, the mapping is likely to change over time, consider the Registry Pattern as a way insulating your code from the effects of such change.
I wouldn't use an if. An if would be less clear than the switch. The switch is telling me that you are comparing the same thing throughout.
Just to scare people, this is less clear than your code:
if (string) reader[discountTypeIndex]) == "A")
p.DiscountType = DiscountType.Discountable;
else if (string) reader[discountTypeIndex]) == "B")
p.DiscountType = DiscountType.Loss;
else if (string) reader[discountTypeIndex]) == "O")
p.DiscountType = DiscountType.Other;
This switch may be OK, you might want to look at #Talljoe suggestion.
Are switches on discount type located throughout your code? Would adding a new discount type require you to modify several such switches? If so you should look into factoring the switch out. If not, using a switch here should be safe.
If there is a lot of discount specific behavior spread throughout your program, you might want to refactor this like:
p.Discount = DiscountFactory.Create(reader[discountTypeIndex]);
Then the discount object contains all the attributes and methods related to figuring out discounts.
You are right to suspect this switch statement: any switch statement that is contingent on the type of something may be indicative of missing polymorphism (or missing subclasses).
TallJoe's dictionary is a good approach, however.
Note that if your enum and database values were integers instead of strings, or if your database values were the same as the enum names, then reflection would work, e.g. given
public enum DiscountType : int
{
Unknown = 0,
Discountable = 1,
Loss = 2,
Other = 3
}
then
p.DiscountType = Enum.Parse(typeof(DiscountType),
(string)reader[discountTypeIndex]));
would suffice.
Yes, this looks like a correct usage of switch statement.
However, I have another question for you.
Why haven't you included the default label? Throwing an Exception in the default label will make sure that the program will fail properly when you add a new discountTypeIndex and forget to modify the code.
Also, if you wanted to map a string value to an Enum, you can use Attributes and reflection.
Something like:
public enum DiscountType
{
None,
[Description("A")]
Discountable,
[Description("B")]
Loss,
[Description("O")]
Other
}
public GetDiscountType(string discountTypeIndex)
{
foreach(DiscountType type in Enum.GetValues(typeof(DiscountType))
{
//Implementing GetDescription should be easy. Search on Google.
if(string.compare(discountTypeIndex, GetDescription(type))==0)
return type;
}
throw new ArgumentException("DiscountTypeIndex " + discountTypeIndex + " is not valid.");
}
I think this depends if you are creating MType add many different places or only at this place. If you are creating MType at many places always having to switch for the dicsount type of have some other checks then this could be a code smell.
I would try to get the creation of MTypes in one single spot in your program maybe in the constructor of the MType itself or in some kind of factory method but having random parts of your program assign values could lead to somebody not knowing how the values should be and doing something wrong.
So the switch is good but maybe the switch needs to be moved more inside the creation part of your Type
I'm not absolutely opposed to switch statements, but in the case you present, I'd have at least eliminated the duplication of assigning the DiscountType; I might have instead written a function that returns a DiscountType given a string. That function could have simply had the return statements for each case, eliminating the need for a break. I find the need for breaks between switch cases very treacherous.
private MyType DoSomething(IDataRecord reader)
{
var p = new MyType
{
Id = (int)reader[idIndex],
Name = (string)reader[nameIndex]
}
p.DiscountType = FindDiscountType(reader[discountTypeIndex]);
return p;
}
private DiscountType FindDiscountType (string key) {
switch ((string) reader[discountTypeIndex])
{
case "A":
return DiscountType.Discountable;
case "B":
return DiscountType.Loss;
case "O":
return DiscountType.Other;
}
// handle the default case as appropriate
}
Pretty soon, I'd have noticed that FindDiscountType() really belongs to the DiscountType class and moved the function.
When you design a language and finally have a chance to remove the ugliest, most non-intuitive error prone syntax in the whole language.
THAT is when you try and remove a switch statement.
Just to be clear, I mean the syntax. This is something taken from C/C++ which should have been changed to conform with the more modern syntax in C#. I wholeheartedly agree with the concept of providing the switch so the compiler can optimise the jump.