Is this kind of a bool method a bad practice? - c#

Sometimes I find myself writing a bool method that looks like this:
public bool isRunning()
{
if (!(move == Moving.None) && staminaRegan == true)
{
if (keyState.IsKeyDown(Keys.Space))
{
EntityAnimation.interval = 10;
return true;
}
else
{
EntityAnimation.interval = 65;
return false;
}
}
else
{
EntityAnimation.interval = 65;
return false;
}
}
(This is XNA by the way) As you can see, I have a bool isRunning in which I made an if statement where Im checking if (Player is moving) && (regains stamina, which is set to false once stamina reaches value lesser than 6.0f)
and then I simply check if Space is pressed, if yes then my Animation is faster(the smaller the interval, the faster is spritesheet changing), and then It sends true value, which means that Player is running, else Im not cause Space is not pressed.
And then I have to repeat this 'else' code outside of the first if statement so it sends that Player is not running if Player is not moving or his stamina Regan is false;
So I was just wondering is this kind of a bool method considered a bad practice(where you retrun true and false value in nested if, and then return false outside nested if and repeat the same code) ?

The method has a side effect, that's why it's a bad practice:
public bool isRunning()
When looking on method's signature we expect just true/false answer and nothing more. However, the method changes the instance's state:
...
if (!(move == Moving.None) && staminaRegan == true)
{
if (keyState.IsKeyDown(Keys.Space))
{
EntityAnimation.interval = 10; // <- Aaa! The interval is changed
return true;
}
...
I suggest splitting the initial method into a property and a method
// No side effect: just answer is running or not
public bool IsRunning {
get {
return (move != Moving.None) && staminaRegan && KeyState.IsKeyDown(Keys.Space);
}
}
// Put the right interval based on instance internal state
// (if it's running etc.)
public void AdjustInterval() {
if (IsRunning) // and may be other conditions
EntityAnimation.interval = 10; //TODO: move magic number into constant
else
EntityAnimation.interval = 65; //TODO: move magic number into constant
}

It is a good practice to have one return statement inside a method. Some argue about this, but it is an opinion.
it is also a good practice to make the if statement clear by removing unnecessary code:
public bool isRunning()
{
bool result = false;
if (move != Moving.None && staminaRegan)
{
if (keyState.IsKeyDown(Keys.Space))
{
EntityAnimation.interval = 10;
result = true;
}
else
{
EntityAnimation.interval = 65;
}
}
else
{
EntityAnimation.interval = 65;
}
return result;
}

You can rewrite the code as follows; then the code isn't repeated:
public bool isRunning()
{
if (move != Moving.None && staminaRegan && keyState.IsKeyDown(Keys.Space))
{
EntityAnimation.interval = 10;
return true;
}
else
{
EntityAnimation.interval = 65;
return false;
}
}
Or if you don't want the redundant else:
public bool isRunning()
{
if (move != Moving.None && staminaRegan && keyState.IsKeyDown(Keys.Space))
{
EntityAnimation.interval = 10;
return true;
}
EntityAnimation.interval = 65;
return false;
}
I would consider introducing a named boolean to self-document somewhat, and I'd rename staminaRegan to staminaIsRegenerating
public bool isRunning()
{
bool isMovingQuickly = (move != Moving.None) && staminaIsRegenerating && keyState.IsKeyDown(Keys.Space);
if (isMovingQuickly)
EntityAnimation.interval = 10;
else
EntityAnimation.interval = 65;
return isMovingQuickly;
}
Most importantly, though, you should rename the method to more accurately describe what it's doing:
public bool CheckIfRunningAndSetAnimationInterval()

I think we write code for people(other developers), of course machine execute a code but 80% of developer's work is reading the code.
Based on that I think flow of reading must be exactly same as flow of executing code - that's why I think multiply return statement not a bad thing, even better then only one return statement on the bottom of your method.

I like this style and i use it too. First, you can read the code more easily and second it has a debugging advantage as you can set breakpoints for the individual else cases. Otherwise you would need to use breakpoint conditions.

Related

A followup if statement

My question is a bit hard to describe so I have written a hypothetical code (nonfunctioning) down below and I wonder if there is a similar alternative in C#:
if (Red == true)
{
i -= 3;
}
else if (Yellow == true)
{
i -= 2
}
then
{
list.Clear();
}
else{}
A "then" function of sorts that both if statements follow if one where to execute. The use of this would simply be so that I do not need to do in this case a list.Clear(); in every if statement.
No there is no syntax construct like your then but you can create a method that clear the list and accept and returns the value to decrement
private int ClearAndDecrementBy(int decrement)
{
list.Clear();
return decrement;
}
and call it as
if(Red)
{
i -= ClearAndDecrementBy(3);
}
else if(Yellow)
{
i -= ClearAndDecrementBy(2);
}
else
{
}
Not really sure that there is any advantage though. The list should be declared at the global class level and this is never a good practice if it is needed only to make it work in this way. So, adding the call to list.Clear inside the if blocks seems more clear and it won't do any harm
Try this:
if(Red == true)
{
i -= 3;
}
else if(Yellow == true)
{
i -= 2
}
else
{
}
if(Red == True || Yellow == true) //You can add more like: Blue == true
{
list.Clear();
}
You could get rid of the "then" statement from your pseudo code and add the following line to the end of everything.
if (Red || Yellow)
{
list.Clear();
}
Try this:
if (Red || Yellow)
{
i = Red ? -3 : -2;
list.Clear();
}
else { }

Visual Studio C# delay function for if statment

I'm looking for a way to create a delay in my code without stopping the rest of the code in this time frame. It has to work as follows. If a condition is true for X amount of seconds, set the alarm bool High. The code below is a part of code where I set the alarms but there needs to be a delay.
I'm very new to C# so try to dumb it down a bit, maybe a small example or links.
if (Valve.Parameter.NormallyOpen == false)
{
if (Valve.Status.Output == true & Valve.Status.Opened == false)
{
Valve.Alarm.NotOpened = true;
}
if (Valve.Status.Output == false & Valve.Status.Closed == false)
{
Valve.Alarm.NotClosed = true;
}
}
Some background info: this will be a valve control block in PLCNext written in C#. The control block should give a alarm if the valve is send open but does not give open feedback within X seconds (takes time to open).
using System;
using System.Threading;
using System.Iec61131Lib;
using Iec61131.Engineering.Prototypes.Types;
using Iec61131.Engineering.Prototypes.Variables;
using Iec61131.Engineering.Prototypes.Methods;
using Iec61131.Engineering.Prototypes.Common;
namespace EclrFirmwareLibrary1
{
[FunctionBlock]
public class Valve_Test
{
[InOut]
public Valve Valve;
[Output]
public bool Output;
double seconds = 1.00; // 1 Second Interval
[Initialization]
public void __Init()
{
//
// TODO: Initialize the variables of the function block here
//
}
[Execution]
public void __Process()
{
Valve.Status.Interlock = Valve.Control.Interlock;
Valve.Status.Opened = Valve.Control.FB_Open;
Valve.Status.Closed = Valve.Control.FB_Closed;
if (Valve.Control.Manual_Mode == true){
Valve.Status.Manual_Mode = true;
Valve.Status.Auto_Mode = false;
}
if (Valve.Control.Auto_Mode == true & Valve.Control.Manual_Mode == false){
Valve.Status.Manual_Mode = false;
Valve.Status.Auto_Mode = true;
}
if(Valve.Status.Interlock == false & Valve.Alarm.General == false)
{
if (Valve.Status.Manual_Mode & Valve.Control.Manual_Control)
{
Output = true;
Valve.Status.Output = true;
}
else if (Valve.Status.Auto_Mode & Valve.Control.Auto_Control)
{
Output = true;
Valve.Status.Output = true;
}
else
{
Output = false;
Valve.Status.Output = false;
}
}
else
{
Output = false;
Valve.Status.Output = false;
}
//Alarms---------------------------------------------------
var startTimeSpan = TimeSpan.Zero;
var periodTimeSpan = TimeSpan.FromSeconds(seconds);
var timer = new System.Threading.Timer((e) =>
{
CheckValve();
}, null, startTimeSpan, periodTimeSpan);
}
private void CheckValve()
{
if (Valve.Parameter.NormallyOpen == false)
{
if (Valve.Status.Output == true & Valve.Status.Opened == false)
{
Valve.Alarm.NotOpened = true;
}
if (Valve.Status.Output == false & Valve.Status.Closed == false)
{
Valve.Alarm.NotClosed = true;
}
}
else
{
if (Valve.Status.Output == false & Valve.Status.Opened == false)
{
Valve.Alarm.NotOpened = true;
}
if (Valve.Status.Output == true & Valve.Status.Closed == false)
{
Valve.Alarm.NotClosed = true;
}
}
if (Valve.Status.Opened == true & Valve.Status.Closed == true)
{
Valve.Alarm.OpenedAndClosed = true;
}
if (Valve.Alarm.NotClosed || Valve.Alarm.NotOpened || Valve.Alarm.OpenedAndClosed)
{
Valve.Alarm.General = true;
}
}
}
}
The important thing to note in this case is that the device you are using includes a .NET runtime implementation that is a subset and specialisation of the complete .NET runtime. This "eCLR" (Embedded CLR) is designed to operate in the deterministic real-time context required for many industrial control applications.
The details of this implementation can be seen in the PLCnext Info Center
When you create a PLCnext C# project in Visual Studio, the project includes a Programming Reference (.chm file). You will see from this reference that the Timer class is not included in the eCLR.
To your question:
There are a number of ways you can implement a delay function in a PLCnext C# function. Perhaps the simplest is to use the DateTime.Now property to get the current system time when the alarm condition is first seen, and remember this value. Then, on each call to the Process method, you can compare the current time to the time when the alarm condition was first seen. When the time period exceeds the preset time, then the output is set.
For more help with questions related to PLCnext Control devices, you can visit the PLCnext Community. There is an active forum there, where you can discuss these sorts of issues with other PLCnext users.
To call a method each x seconds you can use the TimeSpan Method provided by C# and just pass a method called CheckValve, where you put all your code into.
TimeSpan Example:
double seconds = 1.00; // 1 Second Interval
var startTimeSpan = TimeSpan.Zero;
var periodTimeSpan = TimeSpan.FromSeconds(seconds);
var timer = new System.Threading.Timer((e) =>
{
CheckValve();
}, null, startTimeSpan, periodTimeSpan);
I would also advise you to refactor some of your code:
You can replace bool == true checks with just the bool and bool == false checks with just the bool and a ! before the name.
I would also add an else if so if the if is true you don't need to check the other statement.
CheckValve Method:
private void CheckValve() {
if (!Valve.Parameter.NormallyOpen) {
if (Valve.Status.Output && !Valve.Status.Opened) {
Valve.Alarm.NotOpened = true;
}
else if (!Valve.Status.Output && !Valve.Status.Closed)
{
Valve.Alarm.NotClosed = true;
}
}
}

Why my C# code is causing a Stack Overflow

This is the code giving a stack overflow it only happens about half the time and i have no idea why it's doing it. From what I seen it only happens with the Coms(TopCom, etc) are in a mass of numbers so around 5+ then it stack overflows.
public bool getConnected(int d) {
if (topCom.connection != null) {
if (d != topCom.connection.id) {
if (topCom.connection.id == 0) {
return true;
} else if (topCom.connection.connected == true) {
if (Development.instance.currentDos.buttons[topCom.connection.id].getConnected(id)) {
return true;
}
}
}
}
if (leftCom.connection != null) {
if (d != leftCom.connection.id) {
if (leftCom.connection.id == 0) {
return true;
} else if (leftCom.connection.connected == true) {
if (Development.instance.currentDos.buttons[leftCom.connection.id].getConnected(id)) {
return true;
}
}
}
}
if (rightCom.connection != null) {
if (d != rightCom.connection.id) {
if (rightCom.connection.id == 0) {
return true;
} else if (rightCom.connection.connected == true) {
if (Development.instance.currentDos.buttons[rightCom.connection.id].getConnected(id)) {
return true;
}
}
}
}
if (botCom.connection != null) {
if (d != botCom.connection.id) {
if (botCom.connection.id == 0) {
return true;
} else if (botCom.connection.connected == true) {
if (Development.instance.currentDos.buttons[botCom.connection.id].getConnected(id)) {
return true;
}
}
}
}
return false;
}
This happens in recursive functions where you don't have a base condition for ending the recursion. You basically keep calling the function until you reach stack overflow.. Trace your code through and figure out why it calls itself endlessly.
The fact that people here can't really tell what you're trying to accomplish is a code smell of sorts.
A big part of that is the fact that you have an incredible amount of nesting in your code. Nested conditionals increase the difficulty of debugging code, as you're discovering now. Additionally, you could easily combine some of your conditionals - all of your conditionals in any top-level branch can actually be combined into one statement, as follows:
if ((topCom.connection != null && d != topCom.connection.id && topCom.connection.id == 0) ||
(topCom.connection.connected == true &&
Development.instance.currentDos.buttons[topCom.connection.id].getConnected(id)))
{
return true;
}
return false;
As far as I can imagine, there's no point in having separate conditional branches that perform the same function, e.g. if (a) { return true; } else if (b) { return true; }. Just move the logic from else if into the original if conditional.
However, I'd recommend encapsulating some or all of this logic into a separate function, given that it seems like you're performing the same logic on each of your connections. You could create a function like so:
public bool ConnectionIsValid(connectionObject // replace with the actual type)
{
if (topCom.connection != null && d != topCom.connection.id && topCom.connection.id == 0)
|| (topCom.connection.connected == true
&& Development.instance.currentDos.buttons[topCom.connection.id].getConnected(id))
return true;
return false;
}
So that you could then just call ConnectionIsValid on each of your connections, rather than using 80-some lines on conditionals for each connection.
It also seems doubtful that there's a StackOverflowException occurring in this code. Unless you have a circular reference related to any of the objects referenced in this code (in which case, there's a decent chance you used a setter accessor to assign a value to the same variable:
object A
{
set
{
this.A = value;
}
}
which will always cause a stack overflow, it's likely you've introduced some sort of recursion outside the scope of the included code.

How to choose between different if conditions depending on another variable

I've been thinking about this problem for some time, but i just can't think of a solution without having to write duplicate code. The problem in part c# and part pseudo-code:
bool test = true;
if (test == true)
{
if(first condition) {code}
}
else
{
if(different condition) {same code as above)
}
I have to use this part in a performance intensive part of my program and i'd have to transfer 3 big parameters, which is why i'd rather not use a method.
Is there another way to solve this?
if((test && firstCondition) || (!test && differentCondition)) {
//code
}
if ((test && first_condition) || (!test && different_condition)) {
callSomeFunction();
}
I'd do it like this:
// create an inline function to capture the
Action workAction = () => { //work; }
bool test = true;
if (test == true)
{
if(first condition) {workAction(); }
}
else
{
if(different condition) {workAction(); )
}
Depending on the complexity of the conditions, this approach can sometimes help:
bool doBigCall = false;
if (test1)
{
if (test2)
{
doBigCall = true;
}
else
{
// ...
}
}
else
{
// ...
}
if (doBigCall)
{
// write the big bit of code just once
}

break in a if else loop with a counter C#

I have a logic like below and i have a counter
if(condition1 == true)
{
// do something
if (counter==1)
{
// break and go to last else statement
}
}
else if (condition2==true)
{
if (counter == 2)
{
// break and go to last else statement
}
// do something
}
else
{
// do this
}
how do i use break in this logic ?
i tried putting goto tag for else but apparently it is not valid . and i want to avoid switch as there is too much logic.
counter will be 2 in second if else loop and if counter = 2 then first if and secong if else should execute if counter=3 then first if second if else third if else should execute ans so on –
Note: Question was changed, this answer is meanwhile incorrect!
You can change the if/else if to include the counter. Then you don't need a break or goto:
if (condition1 && counter != 1)
{
// do something
}
else if (condition2 && counter != 2)
{
// do something
}
else
{
// do this
}
use something like
if (condition1 && ( counter != 1 || counter != 2 || .... counter!= n )
{
// do something
}
else if (condition2 && (counter != 2 || .. || counter!= n )
{
// do something
}
and so on
else
{
// do this
}
Apart from the fact that a break statement doesn't jump outside an if condition, your code could be
refactored in a more simple way (just pretend that the closed brace after the first if it's only a typo)
if(condition1 ==true && counter != 1)
{
do something
}
else if (condition2==true && counter != 2)
{
do something
}
else
{
do this
}
I suspect that your algorithm could be entirely redesigned, but without more context that's impossible to know.
In the meantime, you can refactor your final else clause into a separate method. You don't actually need to use break (which isn't valid in an if statement anyway), with judicious use of else.
private void MyMethod()
{
if(condition1)
{
// do something
if (counter==1)
{
MyOtherMethod();
}
}
else if (condition2)
{
if (counter == 2)
{
MyOtherMethod();
}
else
{
// do something
}
}
else
{
MyOtherMethod()
}
}
private void MyOtherMethod()
{
// Do what was in your final else clause.
}
Prior to your question edits that moved the `do something' in the first if clause to before the counter check, this would have worked too:
Assuming your various "do something" statements were different things:
if (condition1 && counter != 1)
{
// Do something.
}
else if (condition2 && counter != 1)
{
// Do something.
}
else
{
// Do something else.
}
Just put the logic in the last else block in a seperate function which you can call whenever / wherever you want.
Don't. Using a break and continue in such a big loop adds complexity and clutters your logic.
If a loop is getting too big, use one or more well-named function calls within the loop instead.
bool myCondition = false;
if(condition1 ==true)
{
if (counter==1){myCondition = true;}
// do something
}
else if (condition2==true)
{
if (counter==1){myCondition = true;}
// do something
}
// so on
if(myCondition)
{
// do this
}

Categories