Counting the number of cases in a switch statement - c#

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

Related

Why method should be converted to a property?

I'm creating a method named Check_Finished() but the visual studio won't allow me to do so. Instead, it prompts me as potential fix to convert it into a property. I can't understand why can't we use a method instead of the property here, provided that both have the same purpose and both are gonna return the same thing.
enter image description here
This(below) is the code I want to use.
public bool Check_Finished()
{
if(started && !running)
{
return true;
}
}
This is the one visual studio prompts me to convert to:
public bool Check_Finished
{
get
{
if (started && !running)
{
return true;
}
}
}
which still isn't working. Here this happens:
enter image description here
I can do the following and it works but I wanted to try a different approach just to understand things more.
public bool Finished
{
get { return started && !running; }
}
Sure, you can use a method, but all code paths need to return a value. What if the condition (if-statement) doesn't pass? What should be returned? You don't specify it, leading to a case where no return value is given, which causes the compiler error.
But in general, for such a case, you should prefer using a property, as it represents data and no special calculations have to be done in order to return the value (this wording is not necessarily the rule, but it is easy to "remember" what to use with this mnemonic, though you will get a feeling for that with more experience). Take a look at the MSDN guideline for using properties or methods:
In general, methods represent actions and properties represent data. Properties are meant to be used like fields, meaning that properties should not be computationally complex or produce side effects. When it does not violate the following guidelines, consider using a property, rather than a method, because less experienced developers find properties easier to use.

basic scripting language usable from C#

For a project, I require that my users are able to provide a simple function as a string, and I want to be able to evaluate it from my program.
Let's say the function signature is always int f(int a, int b)
I want to make it so that my users can provide implementations of f written in a basic language.
For instance:
return a*b;
if(a ==1) return b else return 3
And in my program, I want to be able to parse the user input function to make it a real callable function from my C# code. I only require basic features like basic math stuff and conditionals (not even loops).
Is there a basic "language" that exists that would allow me to interpret such functions defined as input and transform them in callable code?
For instance I think that using Lua for this overkill?
Ideally I want something open-source, with minimal codebase and that is widely known to be of good quality. Does such a thing exist? Ideally it should also have implementations in several languages, like C# and Java.
I know the temptation to write my own parser is high but I feel like there must be an out-of-the-box solution for my problem
If you only need math functions you can just have take in a string an eval it in a data table then return the results.
using System.Data;
//string mathExp = "3 * (2+4)"
public string ShiestyEval(string mathExp)
{
DataTable dt = new DataTable();
var v = dt.Compute(mathExp,"");
return v;
}
To get it to be callable from your application, you need to provide an interface in which they can eval there methods, or if you wanna do some shady hack and generate an assembly though Il, and load it you can, it's a little vague on how you want to use it
you can also checkout JSharp
I don't think there is a simple way to do it. But there are some solutions that are easy to use. I really like Irony had a lot of fun with it. But it's a bit abandoned. You can use ANTLR but this one is not simple. You might be able to use Roslyn Api to do what you want it all depends. I am not sure how good of a sandbox do you need but you can use C# scripts
This will allow you to do something like this
ScriptState state = CSharpScript.Run("int Times(int x) { return x * x; }");
var fn = state.CreateDelegate>("Times");
var value = fn(5);
Console.Write(value);

Design or Code Pattern to return multiple optional values from a function

I keep writing several utility, reusable functions in C#. Many functions return multiple values for which I use out or ref parameters. Many functions also have additional information, which may be of use to some callers (but not all callers).
Example, a function to read a CSV file may have additional information like no. of blank lines, no. of lines with duplicate values, and some other statistics.
The additional information could also include warnings, messages, etc.
Not every caller will be interested in this information, so I don't want to include all these as out, ref or Tuples, which will make it mandatory for the caller to declare all such expected variables.
I just wanted to figure out if there is a way to make the additional information available to the callers, so that the caller can choose or retrieve some of the optional additional information it is interested in.
For example, Func 1 can call Func B. After calling it, it gets all the standard return values. Additionally, can it call something like FuncB.GetAdditionalInfo(infoType) without Func B getting executed again?
It may be possible to design this using a class which serves as an intermediary to store all the optional values as well, and then return them to the caller on request; but I want it to be generic enough to be used across all my utility functions.
One possibility is Func B storing all these in some kind of global variables, which the caller can access if required. But if a utility class has several such resuable functions, I will need to have so many public variables, for the additional info of each function!
I am on .NET 4.5 as of now. Is there a design pattern for this? I am open to know if there is a good solution in F#.
Also, I want to avoid too many overloaded versions to achieve this!
Thanks.
I do not contend to present you with the ideal implementation, but here is one that makes sense to me. Design two different data structures: one would represent the options that your function accepts and the second one would be the one that your function returns. For example:
public class Helper
{
// General cover-it-all implementation that accepts an option object
// and analyzes based on the flags that are set in it
public static CSVStatistics AnalyzeCSV(string file, CSVAnalysisOptions options)
{
// define what we are analysing by reading it from the
// from the options object and do your magic here
}
// Specific implementation that counts only blank lines
public static long CountBlankLines(string file)
{
var analysisResult = AnalyseCSV(file, new CSVAnalysisOptions
{
IsCountingBlanks = true
});
//I'm not doing a null check here, because I'm settings the
//flag to True and therefore I expect there to be a value
return analysisResult.BlanksCount.Value;
}
}
// Analysis options structure
public struct CSVAnalysisOptions
{
public bool IsCountingBlanks { get; set; }
public bool IsCountingDuplicates { get; set; }
public bool IsCountingOther { get; set; }
}
// Analysis results structure
public struct CSVStatistics
{
public long TotalLineCount { get; set; }
public long? BlanksCount { get; set; }
public long? DuplicatesCount { get; set; }
}
In the above example CountBlankLines is a specific implementation that counts only blank lines and acts as "sugar" that simplifies the call, while AnalyzeCSV is the method that actually will do the counting. Also, notice how the CSStatistics structure has nullable longs. This will allow you to check if a value is null and therefore know that it was not actually analysed instead of outputting a zero (which is a possible value).
The CSVAnalysisOptions structure could also be replaced by bit flags, you can read about them here - https://www.dotnetperls.com/enum-flags.
I feel like what you're trying to do is to build a very chunky API that can do a whole lot of things in one shot. Generally speaking we don't like chunky API's because they can get complicated especially if there are side-effects or unusual quirks in the interactions between options in the API.
Honestly, the best way to do this is to create a chattier API wherein each call does one thing, does it right and does it well.
When you do this, the code ends up being easier to factor and unit test.
That's not to say that there isn't cause for a moderate amount of chunkiness, but it should be logical.
So for example, if you're cracking an image file to decode, say, a PNG or a JPG, you will need the image width, height, resolution, and color type up front. It would make total sense to grab all of those in one go. Would you need to dig out metadata information or the color profile right away? Probably not.
So it would make sense to have a single call that returns and aggregation of all the basic image information and then separate calls for getting the rest.
"But performance!" you say, "what about performance?!"
Simple. You measure it and see what falls out. A few years ago a wrote a PNG decoder and unlike libpng which reads chunks sequentially, I thought it would be easier to just build a database up front that maps where every chunk of the file is, then refer to that database to find any given chunk. Surprisingly enough, this impacted performance in no significant way and made the consuming code so much easier to read and maintain.
Let things get called multiple times and if there is a performance issue, figure out how to address it. Typically, you do this with a cache or session private to the objects that get the information.
What you're describing sounds like it would be neither easy to read nor to maintain, let alone to test.
Here's an F# pattern that might be suitable for your use case. It's pretty much the same pattern that the Argu library uses for command-line arguments: you declare a discriminated union that contains all the possible "flags" that your function might want to return (I put "flags" in quotation marks because some of them might be more than just booleans), and then your function can return a list of those values. If there are dozens, then a set might be worth it (because a list has to be searched linearly), but if you don't expect to return more than seven or eight such flags, then the extra complexity of a set isn't worth it and you might as well use a list.
Some F# code illustrating how you might use this pattern, with dummy functions where your business logic would go:
type Notifications
| InputWasEmpty
| OutputWasEmpty
| NumberOfBlankLinesInOutput of int
| NumberOfDuplicateLinesInOutput of int
| NumberOfIgnoredErrors of int
// Whatever else...
type ResultWithNotifications<'a> = 'a * Notifications list
// The syntax "TypeA * TypeB" is F# syntax for Tuple<TypeA,TypeB>
// And the 'a is F# syntax for a generic type
type outputRecord = // ... insert your own data type here
// Returns the filename of the output file, plus various notifications
// that the caller can take action on if they want to
let doSomeProcessing data : ResultWithNotifications<outputRecord list>
let mutable notifications = []
let outputFileName = getSafeOutputFilename()
if List.isEmpty data then
notifications <- InputWasEmpty :: notifications
let output = data |> List.choose (fun record ->
try
let result = record |> createOutputRecordFromInputRecord
Some result
except e
eprintfn "Got exception processing %A: %s" record (e.ToString())
None
)
if List.isEmpty output then
notifications <- OutputWasEmpty :: notifications
if List.length output < List.length data then
let skippedRecords = List.length data - List.length output
notifications <- (NumberOfIgnoredErrors skippedRecords) :: notifications
// And so on. Eventually...
output |> writeOutputToFilename outputFileName
outputFileName, notifications // Function result
Hopefully the F# code is comprehensible without explanation, but if there's anything that isn't clear in the above, let me know and I'll try to explain.

Is there an object that contains the parameters of a function?

In a method that is so long that it scrolls off the screen. Just to make life easier as I program, if I want to refer to the variables of a class I can use the Me or this objects depending on which language I am using.
eg. Me.var1 = "Hello"
Is there an object (like Me) that would allow easy reference to the parameters of a function?
eg. params.par1 = "World"
There's no such feature in the language. Local variables and method arguments are treated specially by the .NET jitter, they are heavily optimized at runtime. Anything .NET would do, or you would do, to capture those variables would defeat such optimizations.
A very simple solution is to use Window + Split, it gives you two views on your code. Scroll the top one to the method header, write your code in the bottom one. You can adjust the splitter to give you more room in the bottom window.
Taking advantage of IntelliSense would be another way. Prefix the argument names with a little string, like "par". Then typing "par" in your code automatically gives you the list of argument names in the IntelliSense popup window.
These are however but band-aids for the real problem. As soon as you find yourself reaching like this, your first thought should be to split up the code in the function to make it smaller. There are some hard truths I discovered after thirty years of coding:
Long methods have more bugs. There's a metric for this, called "cyclomatic complexity". The higher the number, the more likely that the code is broken. Well supported by Visual Studio, this blog post is useful.
Code should never be indented more than 3 levels deep. By far the simplest way to discover that your cyclomatic complexity is getting out of hand without running a tool.
A method should never be larger than what fits on the screen. Any code that doesn't fit is a cognitive tax that produces compile errors and bugs. There's a corollary to this, programmers with big monitors create more bugs. The hard rule I use is one inspired by using DOS editors, a method should not have more than 25 lines of code.
Wide code produces a special kind of bug, the nasty kind that you can't see. Anything that's off the screen to the right is code that may have a bug that can take you a long time to discover. VB.NET is especially prone to this kind of bug since it uses end-of-line as a statement terminator. Much improved in VS2010 btw, the underscore is now optional in many cases. Always break your line to avoid this kind of bug.
Plan ahead and write maintainable code. Maintained code is never smaller than the original. If you already have trouble writing the original code then by definition you cannot maintain it. You have to start out small.
Always design first, code later. Long methods are a strong indicator of not thinking about code long enough before you start coding. In itself a strong bug inducer, in addition to writing correct code that just doesn't do the job.
The short answer is no. It seems like you are hoping to use this to distinguish between parameter scope and class scope for function parameters and fields with the same name, unfortunately you can't. Either use different naming schemes, or do the following:
public class MyClass {
private string myString;
private int myInt;
public MyClass(string myString) {
this.myString = myString;
}
public int DoStuff(int myInt) {
this.myInt += myInt;
return this.myInt;
}
}
to be really clear and avoid problems, you could change the names:
public class MyClass {
private string m_myString;
private int m_myInt;
public MyClass(string myString) {
m_myString = myString;
}
public int DoStuff(int myInt) {
m_myInt += myInt;
return m_myInt;
}
}
And you should really start by writing a test before the code, then you can check that you haven't accidentally mixed things up in your code.
Footnote
I include this as people coming to the title of this question may be looking for the following information.
While you say
Just for ease of programming - if I am a long way down in a function I would like to see what parameters there are without having to scroll up
In case you really want to look at your parameters from inside your code for other reasons then you need reflection. This is slow, and it's typical use would be to find a method, then reflect the parameters in that method. For a very comprehensive sample, see MSDN - ParameterInfo Class. The pertinent part of the code is:
foreach (MemberInfo mi in typeof(MyClass).GetMembers() )
{
// If the member is a method, display information about its parameters.
if (mi.MemberType==MemberTypes.Method)
{
foreach ( ParameterInfo pi in ((MethodInfo) mi).GetParameters() )
{
Console.WriteLine("Parameter: Type={0}, Name={1}", pi.ParameterType, pi.Name);
}
}
You should be able to use GetParameters() reflection method
MethodInfo barMI = bar.GetMethod("Foo");
ParameterInfo[] pars = barMI.GetParameters();
foreach (ParameterInfo p in pars)
{
Console.WriteLine(p.Name);
}
You can use this in run time. But for your aim, I would try to refactor the number of functions and their names. I try to keep code length under 80 symbols per line and the number of lines in a class under 100. Which is not always possible, but it's a good objective to decouple stuff and keep classes simple.
A simple way would be to encapsulate your parameters in an object so you can just refer to that, and intellitype (or whatever predictive feature) would show you what properties you have available without having to scroll back up. Like this
public class MyParamObject{
public string FirstParam {get;set;}
public string SecondParam {get;set;}
}
Then you could change your method from
public void MyReallyOvergrownMethod(string firstParam, string secondParam){...
to
public void MyReallyOvergrownMethod(MyParamObject params){...
then you can use the params parameter like this in the method
//Deep inside the method
if(params.FirstParam == "SomeValue"{//Do something
This is a numpty solution to a problem that would be best solved by refactoring your method. Look at loops, and conditionals and get them out into seperate private methods that are named after what they do. Loads of stuff on this, if you search for cleancoders.
In light of your comment "Just for ease of programming - if I am a long way down in a function I would like to see what parameters there are without having to scroll up": in Visual Studio, with code showing, just above the scrollbar there is a little bit you can grab and pull down to split the window. You can then have your function declaration visible in one pane and scroll as much as you like in the other. Or you can use Window menu->Split.

When should one try to eliminate a switch statement? [duplicate]

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.

Categories