Handling switch statement - c#

What's the preferred way to handle the following case:
switch (numberOfActualBytes)
{
case 1: return something1;
case 2: return something2;
case 3: return something3;
case 4: return something4;
}
I know for certain that numberOfActualBytes due to the used contract is in range 1-4.
How should I write the code that doesn't result in not all code paths return a value error?
I suspect I should throw some exception at the end of this function or in default switch case, but probably there is a better solution.

I prefer to throw an out-of-range exception in the default case if the application can be expected to uphold the 1..4 contract. The exception reflects the expectation on the caller that they will give me good data.
If your compiler cannot figure out that the default case solves the not all code paths, then put the return after the switch. But the c# compiler will get it right.

default: return error_code would be my solution.

I would probably do something like this.
declare temp_something = a default value; //Used to check for error.
switch (numberOfActualBytes)
{
case 1: temp_something = something1; break;
case 2: temp_something = something2; break;
case 3: temp_something = something3; break;
case 4: temp_something = something4; break;
}
return temp_something;
Wouldn't this do the same?

Related

C# switch statement with curly braces for each case/default block within the switch statement?

Typically, a switch statement in C# looks like this
switch (sh)
{
case 1:
DoThis();
DoThat();
break;
case 2:
DoThis();
DoThat();
break;
default:
DoThis();
DoThat();
break;
}
But for the first time ever, I saw someone using curly braces for each case statement within a switch statement like below:
switch (sh)
{
case 1:
{
DoThis();
DoThat();
break;
}
case 2:
{
DoThis();
DoThat();
break;
}
default:
{
DoThis();
DoThat();
break;
}
}
Why are these curly braces {, } being used for each case and default blocks of the case statement above?
Why are they needed?
What is the difference?
They are not required, but they are useful if you declare variables with the same name in multiple branches:
switch (sh)
{
case 1:
var test = "test";
Console.WriteLine(test);
break;
case 2:
var test = "test";
Console.WriteLine(test);
break;
}
This will not compile, complaining about conflicting variable names. But if you add braces
switch (sh)
{
case 1:
{
var test = "";
Console.WriteLine(test);
break;
}
case 2:
{
var test = "";
Console.WriteLine(test);
break;
}
}
that will create its own scope for each branch and it will compile fine.
Some people get used to this and always add bracers, even when not defining any variables.
The issue you sometimes face in a switch statement is that all the cases are in the same scope. That means (for example) that you can not use the same variable name in two cases. Consider this:
switch (sh)
{
case 1:
int result = 1;
return result;
case 2:
int result = 2;
return result;
}
This will lead to a compiler error, since you are declaring result twice in the same scope. You remove the error by introducing new scopes in the cases:
switch (sh)
{
case 1:
{
int result = 1;
return result;
}
case 2:
{
int result = 2;
return result;
}
}
Considering that switch cases are somewhat controversial, because they introduce additional complexity, adding extra scopes adds to the confusion. I prefer to use switch blocks in a way that does not lead to the described problem (by keeping the amount of code in the cases low and try to avoid large switch blocks).
In your example the scopes are not needed and I would not use them on a general basis, since this is "unusual" code. And unusual usually means confusing. Your question is a proof to that opinion (and it is an opinion, just to avoid a religious war here), since this construct confused you enough to ask the question.
I belive this is remains of old code. I remember in C when I didnt put the break I would just fall in the next case...
This is no longer relevant and is just code style.
Note you can also do
switch (sh)
{
case 1:
DoThis();
DoThat();
break;
case 2:
{
DoThis();
DoThat();
}break;
case 3:
case 4:
{
DoThis();
DoThat();
}
case 5:
goto case 1;
default:
{
DoThis();
DoThat();
}
}
The break will just leave the Switch but which will be left after leaving the bracket.

C# Change If to switch, how to handle "and"

So I have a task from a worksheet at work:
I have to change these Ifs to a switch, but how do i do it? Heres the Ifs:
if (i<0 || i>15) Console.WriteLine ("A");
else if (i%5<2 && i/3>3) Console.WriteLine ("B");
else if (3<i && i<10) Console.WriteLine ("C");
else if (i&2==2) Console.WriteLine ("D");
else Console.WriteLine ("E");
and here is the switch i made, but that one is bad, but i dont know how to make a good one out of it, i hope you can help me with this.
switch (i)
case (i<0):
case (i>15):
Console.WriteLine ("A“)
Break;
Case (i%5<2 && i/3>3) :
Console.WriteLine ("B“)
Break;
case (3<i && i<10) :
Console.WriteLine ("C");
Break;
Case (i&2==2) :
Console.WriteLine ("D");
Break;
Default
Console.WriteLine ("E");
Break;
It doesnt have to run in a programm, it's just a task from a worksheet
I haven't figured out all the rules completely, but I think what you're after is something like this:
The question wants you to realise that you've got a limited number of results, since the first rule is (i<0 || i>15). This can be the default for a switch statement.
Then you need to work out what would happen for all integers 0-15 and write them into the rest of the switch.
So you're after something along the lines of (although this doesn't have your logic - you can figure that out so you understand what's going on):
switch (i)
{
case 0:
case 2:
case 5:
Console.Write("Something")
break;
case 1:
case 7:
Console.Write("Something Else")
break;
default
Console.WriteLine ("A“)
Break;
}
I think it's:
switch (i)
{
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
Console.WriteLine("C");
break;
case 0:
case 1:
case 3:
case 10:
case 11:
case 12:
case 13:
case 14:
Console.WriteLine("E");
break;
case 2:
Console.WriteLine("D");
break;
case 15:
Console.WriteLine("B");
break;
default:
Console.WriteLine("A");
break;
}
Use a separate variable, in which you have to embed the segmentation logic. Here is a sample:
//using enum
public enum MySwitchableVariable {
NotDefined, //optional
LessThanZero,
MoreThanFifteen,
RestOfFiveLessThanTwoAndFactorMoreThanThree, //its too complex to describe
BetweenThreeAndTen,
RestOfTwoIsTwo,
}
Then you have to make a function which takes an integer and spit out a case of this enum:
public MySwitchableVariable calculate(int i) {
var result = MySwitchableVariable.NotDefined;
// your implementation here
return result;
}
finally you may switch that annoying variable like this:
var Variable = calculate(i);
switch(Variable) {
case MySwitchableVariable.LessThanZero:
// you know the rest
is that what you (or your instructor) want?
Simply you can't do this. Using the switch statement entails that the variable in switch can take a number of discrete constant values.
From the documentation:
The switch statement is a control statement that selects a switch
section to execute from a list of candidates.
Furthermore,
Each case label specifies a constant value. The switch statement transfers control to the switch section whose case label matches the
value of the switch expression (caseSwitch in the example). If no case
label contains a matching value, control is transferred to the default
section, if there is one. If there is no default section, no action is
taken and control is transferred outside the switch statement. In the
previous example, the statements in the first switch section are
executed because case 1 matches the value of caseSwitch.

Return Type using Generics

First, suggestions for a better title are more than welcome.
I'm just starting to learn about Generics so my knowledge is kind of limited. What I'm trying to do is return a Type by calling a method without passing any parameters.
The part I'm failing at is trying to convert my class to T.
Here's my code
private T ReturnSelectedEvent<T>() where T : BaseEvent
{
switch (eventList)
{
case EventItems.Debug: return (T)((object)typeof(DebugEvent));
}
return (T)((object)typeof(BaseEvent));
}
What I want to be returned is the Type so that I may get a static variable in my Class without having to say which class I want it from.
So basically I want to say
DebugEvent.description
Without having to specify the Class, as I have several different of them.
ReturnSelectedEvent<???>().description
My DebugEvent is a child of BaseEvent and is hiding BaseEvent's description by declaring its own.
public class DebugEvent : BaseEvent
{
public static new string description = "This event will fire a debug message when called";
}
I hope I made myself clear, and that what I'm trying to do is possible.
The mess I'm trying to fix with generics is me calling the following multiple times in code.
case EventItems.ToggleEventHandler: toolTip = ToggleEventHandlerEvent.description; break;
case EventItems.PlayerDamage: toolTip = PlayerDamageEvent.description; break;
case EventItems.ControlRestriction: toolTip = ControlRestrictionEvent.description; break;
case EventItems.PlayerForceMove: toolTip = PlayerForceMoveEvent.description; break;
to something more like this
toolTip = ReturnSelectedEvent().description;
EDIT:
Going to explain a bit more of what I'm after.
The system above is used for a menu, basically I have a drop down menu from which I select an item. The options in this menu are based on an Enum, which is the one called EventItems
Now depending on which one I select, I want the description below to match. The description is saved in the BaseEvent as a static string, which I then hide/"override" in my child event with one that better matches that type of event.
Now my idea is that I could possibly compare the enum and depending on what it is, return the corresponding type so that I may set the proper description.
I then plan on using the same method later.
The following is the current mess I'm stuck in, and I was hoping there would be a way to clear it up
if (GUILayout.Button("Add to end"))
{
switch (eventList)
{
case EventItems.Debug: AddObject<DebugEvent>(); break;
case EventItems.Sound: AddObject<SoundEvent>(); break;
case EventItems.ToggleEventHandler: AddObject<ToggleEventHandlerEvent>(); break;
case EventItems.PlayerDamage: AddObject<PlayerDamageEvent>(); break;
case EventItems.ControlRestriction: AddObject<ControlRestrictionEvent>(); break;
case EventItems.PlayerForceMove: AddObject<PlayerForceMoveEvent>(); break;
case EventItems.CameraFocus: AddObject<CameraFocusEvent>(); break;
case EventItems.CameraState: AddObject<CameraStateEvent>(); break;
case EventItems.DestroyObject: AddObject<DestroyObjectEvent>(); break;
case EventItems.PlayerMoveState: AddObject<PlayerMoveStateEvent>(); break;
}
}
if (GUILayout.Button("Insert before"))
{
switch (eventList)
{
case EventItems.Debug: InsertObject<DebugEvent>(loc); break;
case EventItems.Sound: InsertObject<SoundEvent>(loc); break;
case EventItems.ToggleEventHandler: InsertObject<ToggleEventHandlerEvent>(loc); break;
case EventItems.PlayerDamage: InsertObject<PlayerDamageEvent>(loc); break;
case EventItems.ControlRestriction: InsertObject<ControlRestrictionEvent>(loc); break;
case EventItems.PlayerForceMove: InsertObject<PlayerForceMoveEvent>(loc); break;
case EventItems.CameraFocus: InsertObject<CameraFocusEvent>(loc); break;
case EventItems.CameraState: InsertObject<CameraStateEvent>(loc); break;
case EventItems.DestroyObject: InsertObject<DestroyObjectEvent>(loc); break;
case EventItems.PlayerMoveState: InsertObject<PlayerMoveStateEvent>(loc); break;
}
}
if (GUILayout.Button("Insert after"))
{
switch (eventList)
{
case EventItems.Debug: InsertObject<DebugEvent>(loc + 1); break;
case EventItems.Sound: InsertObject<SoundEvent>(loc + 1); break;
case EventItems.ToggleEventHandler: InsertObject<ToggleEventHandlerEvent>(loc + 1); break;
case EventItems.PlayerDamage: InsertObject<PlayerDamageEvent>(loc + 1); break;
case EventItems.ControlRestriction: InsertObject<ControlRestrictionEvent>(loc + 1); break;
case EventItems.PlayerForceMove: InsertObject<PlayerForceMoveEvent>(loc + 1); break;
case EventItems.CameraFocus: InsertObject<CameraFocusEvent>(loc + 1); break;
case EventItems.CameraState: InsertObject<CameraStateEvent>(loc + 1); break;
case EventItems.DestroyObject: InsertObject<DestroyObjectEvent>(loc + 1); break;
case EventItems.PlayerMoveState: InsertObject<PlayerMoveStateEvent>(loc + 1); break;
}
loc++;
}
if (GUILayout.Button("Replace"))
{
switch (eventList)
{
case EventItems.Debug: ReplaceObject<DebugEvent>(); break;
case EventItems.Sound: ReplaceObject<SoundEvent>(); break;
case EventItems.ToggleEventHandler: ReplaceObject<ToggleEventHandlerEvent>(); break;
case EventItems.PlayerDamage: ReplaceObject<PlayerDamageEvent>(); break;
case EventItems.ControlRestriction: ReplaceObject<ControlRestrictionEvent>(); break;
case EventItems.PlayerForceMove: ReplaceObject<PlayerForceMoveEvent>(); break;
case EventItems.CameraFocus: ReplaceObject<CameraFocusEvent>(); break;
case EventItems.CameraState: ReplaceObject<CameraStateEvent>(); break;
case EventItems.DestroyObject: ReplaceObject<DestroyObjectEvent>(); break;
case EventItems.PlayerMoveState: ReplaceObject<PlayerMoveStateEvent>(); break;
}
loc++;
}
I was hoping I could switch out all the different methods to one single one, that would do the same thing, but musch shorter, possibly looking like this instead
AddObject<ReturnSelectedEvent()>();
InsertObject<ReturnSelectedEvent(loc)>();
AddObject<ReturnSelectedEvent(loc + 1)>();
Hopefully this makes things clearer, also the xxObject methods adds an instantiated Event to a List.
So what I was thinking is not possible? If it isn't, any tips for alternative ways of doing this?
I think you don't want the type but an instance of T.
you have to tell your generic method there is a default constructor :
private T ReturnSelectedEvent<T>() where T : BaseEvent, new()
{
return new T();
}
Then if you want, for example get a DebugEvent you can use :
ReturnSelectedEvent<DebugEvent>();
If you really want to use a templated factory, give it a bit more logic. For example, add some parametter in the function that will allow you to switch to null if you're not in debug mode.
this is not possible with generics.
The generic methods are working like a placeholder. The placeholder has to be filled at the moment of the call. Now your are trying to cast the Type BaseEvent to an instance of type T, which is totally wrong and makes no sense. And the method signature says that the method returns an instance of T (which you should pass on call) --> nonsense.
What you try to do is having inheritance over static properties, this is not possible:
But: What do you have in your EventList? Instances of events? Or Types? If instances (which would be way more logic as events are by definition instances) you could do: Create a non-static Getter Method for the events description or an abstract property Description and your problem is solved.
tooltip = eventList.GetDescription();

Switch on enum with default case won't compile.

I'm attempting to use a switch statement over an enumeration as follows:-
public enum myEnum
{
This = 0,
That = 1,
TheOther = 2
}
private void doo_foo (myEnum input)
{
switch (input)
{
case myEnum.This:
// do something;
break;
case myEnum.That:
// do something;
break;
case myEnum.TheOther:
// do something
break;
case default:
// do something;
break;
}
}
but this returns a compilation error on the case default: line:-
Syntax error, '(' expected.
with the little red underline under the colon. Can anyone see what the matter is?
Drop the case from the default line:
switch (input)
{
case myEnum.This:
// do something;
break;
case myEnum.That:
// do something;
break;
case myEnum.TheOther:
// do something
break;
default:
// do something;
break;
}
As Rob Lyndon already answered, the correct syntax is just default:. But to also explain the error message you get, case default is a valid start of a case default(int): expression (which means case 0:), but in order to be valid, default needs to be followed by an opening parenthesis, and that's what the error message is reporting.

C# switch/break

It appears I need to use a break in each case block in my switch statement using C#.
I can see the reason for this in other languages where you can fall through to the next case statement.
Is it possible for case blocks to fall through to other case blocks?
Thanks very much, really appreciated!
Yes, you can fall through to the next case block in two ways. You can use empty cases, which don't need a break, or you can use goto to jump to the next (or any) case:
switch (n) {
case 1:
case 2:
case 3:
Console.WriteLine("1, 2 or 3");
goto case 4;
case 4:
Console.WriteLine(4);
break;
}
The enforcement of "break" is there to stop bugs. If you need to force a fall-thru then use "goto case " (replace the with appropriate value)
the following example shows what you can do:
switch(n)
{
case 1:
case 2:
//do something for 1+2
//...
goto case 3;
case 3:
//do something for 3, and also extra for 1+2
//...
break;
default:
//do something for all other values
//...
break;
}
See http://msdn.microsoft.com/en-us/library/06tc147t%28VS.80%29.aspx
C# doesn't support implicit fall through construct, but the break (or goto) nonetheless has to be there (msdn). The only thing you can do is stack cases in the following manner:
switch(something) {
case 1:
case 2:
//do something
break;
case 3:
//do something else
}
but that break (or another jump statement like goto) just needs to be there.
In my C# (.NET 1.1, CF) code, both of these are allowed:
switch (_printerChoice)
{
case BeltPrintersEnum.ZebraQL220:
return new ZebraQL220Printer();
break;
case BeltPrintersEnum.ONeal:
return new ONealPrinter();
break;
default:
return new ZebraQL220Printer();
break;
}
switch (_printerChoice)
{
case BeltPrintersEnum.ZebraQL220:
return new ZebraQL220Printer();
case BeltPrintersEnum.ONeal:
return new ONealPrinter();
default:
return new ZebraQL220Printer();
}
...but with the breaks in, they are grayed out, so considered moot. So, at least in my case, they are allowed but not required.

Categories