Refactor switch statement that assigns different variables depending on case? - c#

How can I refactor a switch statement that is in multiple places in code that assigns a value to a variable depending on which case is thrown, for example:
int a = 0;
int b = 0;
switch(c)
{
case "1"
a = 1;
break;
case "2"
b = 2;
break;
}
In the above example, resharper will use one of the variables as the return and the other as an out parameter. Is there another way to do it, maybe not extracting out the whole switch block.

This code block has a couple of different ways of refactoring it to make it more reusable without having it copied over in places. However, they're going to require reworks of things:
Are the objects logically grouped somehow?
If so, then you could make an object to represent them, and then refactor to return the object set with values.
var myObj = SetObjectAccordingTo(c);
protected SomeObj SetObjectAccordingTo(string c)
{
var myObj = new SomeObj();
switch(c)
{
case "1": myObj.a = 1;
break;
case "2": myObj.b = 2;
break;
}
return myObj;
}
If they are not logically grouped, and each is assigned a value...
Then logic for determining each value needs to be split.
a = DetermineValueForA(c);
b = DetermineValueForB(c);
And each method deals only with the cases where a is involved.
If they are not logically grouped, and only certain values are assigned...
Then there is not much optimization that can be performed save moving the respective values to member variables and then calling each with that specific method.
If you could provide a sample of what you're trying to do, we could offer a solution more than likely.

You mean you'd like to extract this as a method? You might consider returning a struct (or perhaps a class) if A and B are related in some manner. Perhaps, NDA permitting, you could show us a code fragment in context so it might become clearer how to solve this.

Related

Assign a formula at runtime for accessing elements of List

The scenario is that I have say two different types of cases - case 1 and case 2. For case 1 and case 2 each I have a certain startIndex, endIndex and a formula for accessing the elements of a List.
Now for assigning values startIndex and endIndex I am preferring a normal switch case, however I am at loss for the formula for accessing elements. For case 1 it is say something like List[ a+i ] and for case 2 it is say List[a + (i-b)].
One way can be to have a for loop like this
for(int i=0;;i++)
{
if(case is 1)
then f=a+i
else if(case 2)
then f=a+(i-b)
}
I thought of using delegates. however, as per my knowledge they need to be made global. Actions do not return value. Func can be used but one expression/formula takes only one element (int) and the other takes 3. I need something in lines to this like that anonymous function can be assigned any of above mentioned formulae at runtime from the switch case (as the cases might and will increase in future).
Thank you.
I thought of using delegates. however, as per my knowledge they need
to be made global.
This is not true (actually, there are no truly global variables in C#, since each and every variable needs to be encapsulated inside an object). A public delegate type is indeed visible to all code after referencing the assembly containing this type's code, but a variable of such type can be private.
What I recommend in your situation is to have some sort of mapping from case numbers to delegates. A good idea is to use a Dictionary<TKey, TValue> if you have at most one delegate per case. This dictionary can be stored as a private variable inside the class where your method resides.
public class MyClass
{
private Dictionary<int, Delegate> _delegateMapping = new Dictionary<int, Delegate>;
}
There are a couple of ways you can add elements do the dictionary in the constructor: passing the already populated dictionary, passing an array of delegates, creating these delegates in the constructor itself. Either way, you'll end up with a dictionary of Delegate types, so you'll need to use a cast to be able to use them in your code properly.
for (int i = 1; i < _delegateMapping.Count; i++)
{
switch (i)
{
case 1:
var f = (Action<int>)_delegateMapping[1];
f(i);
break;
case 2:
var f = (Action<int, int>)_delegateMapping[2];
f(i, a);
break;
}
}
Of course I'm greatly improvising here.
It is important to note that if the type of delegate changes inside the dictionary, you will have to modify the cast accordingly inside the switch statement. Otherwise, if no implicit cast exists, you'll get a runtime exception.
Hi guys thank you so very much for your feedbacks. I finally found the solution with Func. This is what my code looks like. I had to manipulate the Func usage a little. I made almost all the vars which I have to use in the Func as global/local to the function where I write these Funcs. My apologies, if I was not able to explain my problem properly.
int i = -1;
Func<int,int> formula = null;
switch(f)
{
case 1:
{
formula = new Func<int,int>(index => { return i; });
}
break;
case 2:
{
formula = new Func<int, int>( index => { return s- (i * c); } );//here s and c are global variables.
}
break;
}
i = startIndex;
while(i < endIndex)
{
var Obj= List[formula.Invoke(i)];
//my code goes here
i++;
}
Let me know if my solution is correct w.r.t performance, logic, C# programming, etc.. :)
EDITED::
#usr and #Kapol I tried the way you suggested and tried to improvise the code like this.
private Dictionary<int, Func<int[], int>> indexFormulae;
private void assignDelegates()
{
indexFormulae = new Dictionary<int, Func<int[], int>>();
indexFormulae.Add(0, getFormula_1);
indexFormulae.Add(1, getFormula_2);
}
private void someFunction(int sp)
{
int i = 0;
Func<int[], int> formula = null;
indexFormulae.TryGetValue(formation,out formula);
i = startIndex;
while (i < endIndex)
{
int[] intValues = new int[] {i,sp,globalVar };
var Obj = List[formula.Invoke(intValues)];
//My code here
i++;
}
}
private int getFormula_1(params int[] intValues)
{
return intValues[0];
}
private int getIndex_Vertical(params int[] intValues)
{
return intValues[1] - (intValues[0] * intValues[2]);
}
So, that with this now I can use these two getFormula methods anywhere in this class rather than keeping them anonymous. and also I think I will stick to params because I might have N number of int params in future for other functions.

c# which is the better way to declare two parameters

I have a very quick question about the best way to use two variables. Essentially I have an enum and an int, the value for which I want to get within several ifs. Should I declare them outside the if's or inside - consider the following examples:
e.g.a:
public void test() {
EnumName? value = null;
int distance = 0;
if(anotherValue == something) {
distance = 10;
value = getValue(distance);
}
else if(anotherValue == somethingElse) {
distance = 20;
value = getValue(distance);
}
if (value == theValueWeWant){
//Do something
}
OR
e.g.2
public void test() {
if(anotherValue == something) {
int distance = 10;
EnumType value = getValue(distance);
if (value == theValueWeWant){
//Do something
}
else if(anotherValue == somethingElse) {
int distance = 20;
EnumType value = getValue(distance);
if (value == theValueWeWant){
//Do something
}
}
I am just curious which is best? or if there is a better way?
Purely in terms of maintenance, the first code block is better as it does not duplicate code (assuming that "Do something" is the same in both cases).
In terms of performance, the difference should be negligible. The second case does generate twice as many locals in the compiled IL, but the JIT should notice that their usage does not overlap and optimize them away. The second case is also going to cause emission of the same code twice (if (value == theValueWeWant) { ...), but this should also not cause any significant performance penalty.
(Though both aspects of the second example will cause the compiled assembly to be very slightly larger, more IL does not always imply worse performance.)
Both examples do two different things:
Version 1 will run the same code if you get the desired value, where as Version 2 will potentially run different code even if you get the desired value.
There's a lot of possible (micro)optimizations you could do.
For Example, if distance is only ever used in getValue(distance), you could get rid of it entirely:
/*Waring, micro-optimization!*/
public void test() {
EnumType value = getValue((anotherValue == something) ? 10 : (anotherValue == somethingElse) ? 20 : 0);
if (value == theValueWeWant){
//Do something
}
}
If you wish to use those later on, then g for the second method. Those variables will be lost as soon as they're out of scope.
Even if you don't want to use them later, declaring them before the if's is something you should do, to avoid code repetition.
This question is purely a matter of style and hence has no correct answer, only opinions
The C# best practice is generally to declare variables in the scope where they are used. This would point to the second example as the answer. Even though the types and names are the same, they represent different uses and should be constrained to the blocks in which they are created.

Not all code paths return a value - but they do

The following extract of code is failing to compile resulting in not code paths return a value. Both types Test1StandardChargeCalculator and Test2StandardChargeCalculator are derived from the return type.
I know how to fix this, but my question is why should I have to? A bool is a value type - hence can only represent true or false, both of which are catered for in this snippet. So why the failed compilation?
internal StandardChargeCalculator Create()
{
bool value = true;
switch (value)
{
case true:
return new Test1StandardChargeCalculator();
case false:
return new Test2StandardChargeCalculator();
}
} //not all code paths return a value
When using a switch statement, the compiler does not understand that when you are using a boolean type to switch on there can only be two results.
The error occurs because you do not have a default case.
Don't use a switch for boolean test - use an if statement:
bool value = true;
if(value)
{
return new Test1StandardChargeCalculator();
}
return new Test2StandardChargeCalculator();
Why do you think the compiler should special-case boolean and detect that all possible values have a case statement?
If you were writing a compiler, would you invest development effort and increase the risk of bugs by implementing this?
In Absence of evidence is not evidence of absence Eric Lippert writes about the limitations of 'proofing' that a variable is unassigned and the weaker aim of the compiler in this regard:
that we're not interested in proving for certain that x is unassigned.
We're interested in proving for certain that x is assigned! If we can
prove that for certain, then x is "definitely assigned". If we cannot
prove that for certain then x is "not definitely assigned".
Which does not directly explain this example but note that it is the same issue as :
int x;
if (a < 10)
x = 0;
else if (a >= 10)
x = 1;
y = x; // x is 'unassigned'
We can quickly see that x will always be assigned, the compiler does not even attempt to find out.
To my understanding it is inconsistant to the definition of the switch which says:
If no case expression matches the switch value, then control is transferred to the statement(s) that follow the optional default label. If there is no default label, control is transferred outside the switch.
You are right: there should be no compiler error. So, this might be a case where no answer is the answer. You will have to live with it.
switch (answer)
{
...
default:
return "It is as it is"
}
Maybe better solution would be
internal StandardChargeCalculator Create()
{
StandardChargeCalculator result = null;
bool value = true;
switch (value)
{
case true:
result = new Test1StandardChargeCalculator();
break;
case false:
result = new Test2StandardChargeCalculator();
break;
}
return result;
}

Non Static/Constant values in case statements within a Switch

I'd like to do something like this in c sharp:
int i = 0;
foreach ( Item item in _Items )
{
foreach (Field theField in doc.Form.Fields)
{
switch (theField.Name)
{
case "Num" + i++.ToString(): // Number of Packages
theField.Value = string.Empty;
break;
}
}
}
I have 20 or so fields named Num1, Num2, etc. If I can do this all in one statement/block, I'd prefer to do so.
But the compiler complains that the case statements need to be constant values. Is there a way to use dynamic variables in the case statement so I can avoid repeating code?
I just thought I'd mention, the purpose of this method is to populate the fields in PDF form, with naming conventions which I can not control. There are 20 rows of fields, with names like "Num1" - "Num20". This is why string concatenation would be helpful in my scenario.
No. This is simply part of the language. If the values aren't constants, you'll have to use if/else if or a similar solution. (If we knew more details about what you were trying to achieve, we may be able to give more details of the solution.)
Fundamentally, I'd question a design which has a naming convention for the fields like this - it sounds like really you should have a collection to start with, which is considerably easier to work with.
Yes case value must be able to be evaluated at compile time. How about this instead
foreach (Field theField in doc.Form.Fields)
{
if(theField.Name == ("Num" + i++))
{
theField.Value = string.Empty;
}
}
How about:
int i = 0;
foreach ( Item item in _Items )
doc.Form.Fields.First(f=>f.Name == "Num" + i++.ToString()).Value = string.Empty;
Not sure what the purpose of item is in your code though.
No. There is no way.
How about replacing the switch with:
if (theField.Name.StartsWith("Num"))
theField.Value = string.Empty;
or some similar test?
var matchingFields =
from item in _Items
join field in doc.Form.Fields
on "Num" + item.PackageCount equals field.Name
select field;
foreach (var field in matchingFields)
{
field.Value = string.Empty;
}
For more efficiency include a DistinctBy on field Name after getting the matching fields (from MoreLINQ or equivalent).
Also consider that every time you concatenate two or more strings together the compiler will create memory variables for each of the component strings and then another one for the final string. This is memory intensive and for very large strings like error reporting it can even be a performance problem, and can also lead to memory fragmentation within your programs running, for long-running programs. Perhaps not so much in this case, but it is good to develop those best-practices into your usual development routines.
So instead of writing like this:
"Num" + i++.ToString()
Consider writing like this:
string.Format("{0}{1}", "Num", i++.ToString());
Also you may want to consider putting strings like "Num" into a separate constants class. Having string constants in your code can lead to program rigidity, and limit program flexibility over time as your program grows.
So you might have something like this at the beginning of your program:
using SysConst = MyNamespace.Constants.SystemConstants;
Then your code would look like this:
string.Format("{0}{1}", SysConst.Num, i++.ToString());
And in your SystemConstants class, you'd have something like this:
/// <summary>System Constants</summary>
public static class SystemConstants
{
/// <summary>The Num string.</summary>
public static readonly string Num = #"Num";
}
That way if you need to use the "Num" string any place else in your program, then you can just use the 'SysConst.Num'
Furthermore, any time you decide to change "Num" to "Number", say perhaps per a customer request, then you only need to change it in one place, and not a big find-replace in your system.

c# performance: type comparison vs. string comparison

Which is faster? This:
bool isEqual = (MyObject1 is MyObject2)
Or this:
bool isEqual = ("blah" == "blah1")
It would be helpful to figure out which one is faster. Obviously, if you apply .ToUpper() to each side of the string comparison like programmers often do, that would require reallocating memory which affects performance. But how about if .ToUpper() is out of the equation like in the above sample?
I'm a little confused here.
As other answers have noted, you're comparing apples and oranges. ::rimshot::
If you want to determine if an object is of a certain type use the is operator.
If you want to compare strings use the == operator (or other appropriate comparison method if you need something fancy like case-insensitive comparisons).
How fast one operation is compared to the other (no pun intended) doesn't seem to really matter.
After closer reading, I think that you want to compare the speed of string comparisions with the speed of reference comparisons (the type of comparison used in the System.Object base type).
If that's the case, then the answer is that reference comparisons will never be slower than any other string comparison. Reference comparison in .NET is pretty much analogous to comparing pointers in C - about as fast as you can get.
However, how would you feel if a string variable s had the value "I'm a string", but the following comparison failed:
if (((object) s) == ((object) "I'm a string")) { ... }
If you simply compared references, that might happen depending on how the value of s was created. If it ended up not being interned, it would not have the same reference as the literal string, so the comparison would fail. So you might have a faster comparison that didn't always work. That seems to be a bad optimization.
According to the book Maximizing .NET Performance
the call
bool isEqual = String.Equals("test", "test");
is identical in performance to
bool isEqual = ("test" == "test");
The call
bool isEqual = "test".Equals("test");
is theoretically slower than the call to the static String.Equals method, but I think you'll need to compare several million strings in order to actually detect a speed difference.
My tip to you is this; don't worry about which string comparison method is slower or faster. In a normal application you'll never ever notice the difference. You should use the way which you think is most readable.
The first one is used to compare types not values.
If you want to compare strings with a non-sensitive case you can use:
string toto = "toto";
string tata = "tata";
bool isEqual = string.Compare(toto, tata, StringComparison.InvariantCultureIgnoreCase) == 0;
Console.WriteLine(isEqual);
How about you tell me? :)
Take the code from this Coding Horror post, and insert your code to test in place of his algorithm.
Comparing strings with a "==" operator compares the contents of the string vs. the string object reference. Comparing objects will call the "Equals" method of the object to determine whether they are equal or not. The default implementation of Equals is to do a reference comparison, returning True if both object references are the same physical object. This will likely be faster than the string comparison, but is dependent on the type of object being compared.
I'd assume that comparing the objects in your first example is going to be about as fast as it gets since its simply checking if both objects point to the same address in memory.
As it has been mentioned several times already, it is possible to compare addresses on strings as well, but this won't necessarily work if the two strings are allocated from different sources.
Lastly, its usually good form to try and compare objects based on type whenever possible. Its typically the most concrete method of identification. If your objects need to be represented by something other than their address in memory, its possible to use other attributes as identifiers.
If I understand the question and you really want to compare reference equality with the plain old "compare the contents": Build a testcase and call object.ReferenceEquals compared against a == b.
Note: You have to understand what the difference is and that you probably cannot use a reference comparison in most scenarios. If you are sure that this is what you want it might be a tiny bit faster. You have to try it yourself and evaluate if this is worth the trouble at all..
I don't feel like any of these answers address the actual question. Let's say the string in this example is the type's name and we're trying to see if it's faster to compare a type name or the type to determine what it is.
I put this together and to my surprise, it's about 10% faster to check the type name string than the type in every test I ran. I intentionally put the simplest strings and classes into play to see if it was possible to be faster, and turns out it is possible. Not sure about more complicated strings and type comparisons from heavily inherited classes. This is of course a micro-op and may possibly change at some point in the evolution of the language I suppose.
In my case, I was considering a value converter that switches based on this name, but it could also switch over the type since each type specifies a unique type name. The value converter would figure out the font awesome icon to show based on the type of item presented.
using System;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApp1
{
public sealed class A
{
public const string TypeName = "A";
}
public sealed class B
{
public const string TypeName = "B";
}
public sealed class C
{
public const string TypeName = "C";
}
class Program
{
static void Main(string[] args)
{
var testlist = Enumerable.Repeat(0, 100).SelectMany(x => new object[] { new A(), new B(), new C() }).ToList();
int count = 0;
void checkTypeName()
{
foreach (var item in testlist)
{
switch (item)
{
case A.TypeName:
count++;
break;
case B.TypeName:
count++;
break;
case C.TypeName:
count++;
break;
default:
break;
}
}
}
void checkType()
{
foreach (var item in testlist)
{
switch (item)
{
case A _:
count++;
break;
case B _:
count++;
break;
case C _:
count++;
break;
default:
break;
}
}
}
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
checkTypeName();
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
sw.Restart();
for (int i = 0; i < 100000; i++)
{
checkType();
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
}
}
}

Categories