Could I write the following logic in a simpler, more easy-to-read way? The below does what I need, but it is very messy:
if (IsChanged == true)
{
return;
}
// Executed when the close (x) button is pressed,
// as the Status string is not yet set to a real value...
else if (Status == "" && IsChanged == false)
{
CancelClose();
}
// saving logic falls to here...
else if (IsChanged == false && Status == "saving")
{
IsChanged = false;
}
Thanks
if (isChanged) return;
switch (Status) {
case "":
CancelClose();
break;
case "saving":
// IsChanged = false;
break;
}
This is about as neat as it gets. Note that because you return if isChanged is true you can further on always assume that isChanged is false.
This is a bit cleaner:
if (IsChanged)
{
}
else if (Status == "saving")
{
}
else if (Status == "")
{
}
else
{
}
I would recommend you use an enum to represent the status. This will allow your code to be strongly typed.
public enum Status
{
Closing,
Saving,
Changed,
}
Then you can use a nice switch statement to decide what action to take.
switch (_status)
{
case Status.Saving:
break;
case Status.Closing:
break;
case Status.Changed:
break;
default:
break;
}
if(IsChanged)
return;
if(Status == "saving")
{
// save
}
else if(string.IsNullOrEmpty(Status))
{
CancelClose();
}
Since you return if IsChanged==true, you don't need it in the other ifs.
if (IsChanged == true)
return;
switch (Status)
{
case "":
CancelClose();
break;
case "saving":
break;
}
yes:
if (IsChanged) return;
if (String.IsNullOrEmpty(Status)) CancelClose();
cut the first else if to just if. If IsChanged is true the "else" will never be reached.
remove the IsChanged==false from your other ifs because they are always true.
Think about enums instead of strings for your status.
I'd recommend:
if (IsChanged)
{
return;
}
if (CurrentStatus == Status.None)
{
CancelClose();
return;
}
if (CurrentStatus == Status.Saving)
{
// IsChanged = false;
}
if(!IsChanged) {
if (Status == "saving") // saving logic falls to here...
{
// IsChanged = false;
}
else if (Status == "") // Executed when the close (x) button is pressed, as the Status string is not yet set to a real value...
{
CancelClose();
}
} else {
return;
}
It can be simplifed in to
if (IsChanged)
{
return;
}
else if (Status == "") // Executed when the close (x) button is pressed, as the Status string is not yet set to a real value...
{
CancelClose();
}
else if (Status == "saving") // saving logic falls to here...
{
// IsChanged = false;
}
You do not need the == True in the first check, as it already is true or false. you do not need to check for false in the other choices because if it is not true it must be false.
if (IsChanged) return;
if (Status == "saving")
{
//IsChanged = false;
}
else if (Status = "")
{
CancelClose();
}
I'd avoid beginning your variable names with uppercase.
if (IsChanged)
return;
if (String.IsNullOrEmpty(Status)) // better use this unless you would like a
CancelClose(); // nullPointerException
else if (Status.equals("Saving"))
// whatever you want for save
I'm not familiar with c#, but it supports the conditional operator
condition ? first_expression : second_expression;
Since I'm not familiar with c#, I won't try to re-write your code, but in any case, the ternary operator can lead to pleasing concision in some places.
Related
This is the function i wanted to test,
public bool SetCurrentState(string state) // set the status of the building controller
{
switch (state.ToLower())
{
case "open":
// set the new state according to the current state
if ((currentState == "out of hours" || currentState == "open") && doorManger.OpenAllDoors())
{
currentState = state.ToLower();
}
// go to the history state if the current state is fire alarm or fire drill
else if (currentState == "fire alarm" || currentState == "fire drill")
{
currentState = historyState;
}
else
{
return false;
}
break;
case "out of hours":
// set the new state according to the current state
if (currentState == "open" || currentState == "closed" || currentState == "out of hours")
{
currentState = state.ToLower();
}
// go to the history state if the current state is fire alarm or fire drill
else if (currentState == "fire alarm" || currentState == "fire drill")
{
currentState = historyState;
}
else
{
return false;
}
break;
default:
return false;
}
return true;
}
Above function is inside a class called BuildingController. That class has a public member call doorManager which is an object of IDoorManager class.
this is the test case i wrote,
[Test]
public void test()
{
// Arrange
BuildingController buildingController = new BuildingController("b0010");
buildingController.doorManger.OpenAllDoors().Returns(false);
//Act
bool result = buildingController.SetCurrentState("open");
string state = buildingController.GetCurrentState();
//Assert
Assert.AreEqual(false, result);
Assert.AreEqual("out of hours", state);
}
I want to return false for doorManger.OpenAllDoors() position while I'm running the test case. Is it possible?
If the doorManger.OpenAllDoors() returns false then state is "out of hours".
If it returns true then state is open
So I want to check the true and false at the same time.
I am a complete newbie and i am stuck on a small problem
I want the user to only be able to have yes or no as an answer.
This is what I came up with
static public bool askBool(string question)
{
try
{
Console.Write(question);
return Console.ReadLine() == "y";
}
catch (Exception)
{
throw new FormatException("Only y or n Allowed");
}
}
The problem is entering any other letter then 'y' will result in false, how can I best solve this ?
Thank you in advance.
EDIT (from comment question)
try
{
Console.Write(question);
return int.Parse(Console.ReadLine());
}
catch (Exception)
{
throw new FormatException("Please Enter a Number");
}
I doubt if you want an exception to be thrown - there's nothing exceptional if the user puts OK instead of yes; I suggest to keep asking until "yes" or "no" are read:
public static AskBool(string question) {
while (true) {
// If we have a question to ask (the question is not empty one)...
if (!string.IsNotNullOrWhiteSpace(question))
Console.WriteLine(question); // ... ask it
// Trim: let be nice and trim out leading and trailing white spaces
string input = Console.ReadLine().Trim();
// Let's be nice and accept "yes", "YES", "Y" etc.
if (string.Equals(input, "y", StringComparison.OrdinalIgnoreCase) ||
string.Equals(input, "yes", StringComparison.OrdinalIgnoreCase))
return true;
else if (string.Equals(input, "n", StringComparison.OrdinalIgnoreCase) ||
string.Equals(input, "no", StringComparison.OrdinalIgnoreCase))
return false;
// In case of wrong user input, let's give a hint to the user
Console.WriteLine("Please, answer yes or no (y/n)");
}
}
Here the method will only return true or false if user has entered true or false.If user enters any word the loop will just continue to ask him for input until he enters y or n
you can give it a try by doing following changes
static public bool askBool(string question)
{
bool boolToReturn = false;
Console.Write(question);
while (true)
{
string ans = Console.ReadLine();
if (ans != null && ans == "y")
{
boolToReturn = true;
break;
}
else if ( ans != null && ans == "n")
{
boolToReturn = false;
break;
}
else
{
Console.Write("Only y or n Allowed");
}
}
return boolToReturn;
}`
Answer to second question:-
`
public static int askInt(string question)
{
Int intToReturn = false;
Console.Write(question);
while (true)
{
string ans = Console.ReadLine();
if (int.TryParse(and,out intToreturn))
break;
else
Console.Write("Only number Allowed");
}
return intToReturn;
}`
A bit more simplified version of Dmitry's answer with switch (what I normally do for this kind of scenarios):
static public bool askBool(string question)
{
while(true)
{
Console.Clear();
Console.Write(question);
var input = Console.ReadLine().Trim().ToLowerInvariant();
switch (input)
{
case "y":
case "yes": return true;
case "n":
case "no": return false;
}
}
}
Also I'd consider changing .ReadLine() to .ReadKey() because what we really need here is just 'y' or 'n'... One key is enough.
We use Exceptions mostly for scenarios when unexpected value will lead to some error. We don't throw an exception when we expect user to enter rubbish values and handle them.
You want to throw the exception, not catch it. Example:
static public bool askBool(string question)
{
Console.Write(question);
var input = Console.ReadLine();
if (input == "y")
{
return true;
}
else if(input == "n")
{
return false;
}
else//It's not y or n: throw the exception.
{
throw new FormatException("Only y or n Allowed");
}
}
Of course, you must then capture the 'FormatException' where you call this method.
Something like this?
if (Console.ReadLine() == "y")
{
return true;
}
else if (Console.ReadLine() == "n")
{
return false;
}
else {
throw new Exception("only y and n allowed...");
}
Here another idea:
public static bool ReadUserYesOrNo()
{
bool userSaysYes = true;
Console.Write("Y\b");
bool done = false;
while (!done)
{
ConsoleKeyInfo keyPressed = Console.ReadKey(true); // intercept: true so no characters are printed
switch (keyPressed.Key) {
case ConsoleKey.Y:
Console.Write("Y\b"); // print Y then move cursor back
userSaysYes = true;
break;
case ConsoleKey.N:
Console.Write("N\b"); // print N then move cursor
userSaysYes = false;
break;
case ConsoleKey.Enter:
done = true;
Console.WriteLine();
break;
}
}
return userSaysYes;
}
This will print the default value Y to the console. By pressing Y or N the user can toggle between the two values. The character in the console output will be overwritten. Pressing 'enter' selects the choice and the method returns the result.
I have written the code below to evaluate a boolean expression. The expression is coded in the form of objects.
It's one of those moments when I look at the code and think: I'm sure there's a better way to code that, using less boolean variables but can't see the right way to go. Any help? Unit tests have been written and are passing for a variety of inputs.
if (tree == null || !tree.IsActive || tree.FilterNodes == null)
{
return false;
}
var result = false;
foreach (var filter in tree.FilterNodes.Where(a => a.IsActive && a.ConditionNodes != null))
{
var tempBool = false;
foreach (var condition in filter.ConditionNodes.Where(a => a.IsActive))
{
if (!string.IsNullOrWhiteSpace(condition.FieldName) && values.ContainsKey(condition.FieldName))
{
var value = values[condition.FieldName];
if (filter.LogicalOperator == LogicalOperator.Or && ApplyCondition(condition.ConditionOperator, value, condition.FieldValue))
{
tempBool = true;
break;
}
else if (filter.LogicalOperator == LogicalOperator.And)
{
tempBool = ApplyCondition(condition.ConditionOperator, value, condition.FieldValue);
if (!tempBool)
{
break;
}
}
else
{
tempBool = false;
}
}
else if (!string.IsNullOrWhiteSpace(condition.FieldName) && filter.LogicalOperator == LogicalOperator.And)
{
tempBool = false;
}
}
result = tempBool;
if (!result)
{
break;
}
}
return result;
You could set tempBool = false first thing in the loop and leave out the else and last else if:
foreach (var condition in filter.ConditionNodes.Where(a => a.IsActive))
{
tempBool = false;
if (!string.IsNullOrWhiteSpace(condition.FieldName) && values.ContainsKey(condition.FieldName))
{
var value = values[condition.FieldName];
if (filter.LogicalOperator == LogicalOperator.Or && ApplyCondition(condition.ConditionOperator, value, condition.FieldValue))
{
tempBool = true;
break;
}
else if (filter.LogicalOperator == LogicalOperator.And)
{
tempBool = ApplyCondition(condition.ConditionOperator, value, condition.FieldValue);
if (!tempBool)
{
break;
}
}
}
}
EDIT
It gets even simpler:
foreach (var condition in filter.ConditionNodes.Where(a => a.IsActive))
{
tempBool = false;
if (!string.IsNullOrWhiteSpace(condition.FieldName) && values.ContainsKey(condition.FieldName))
{
var value = values[condition.FieldName];
tempBool == ApplyCondition(condition.ConditionOperator, value, condition.FieldValue);
if ((filter.LogicalOperator == LogicalOperator.And && !tempBool) || (filter.LogicalOperator == LogicalOperator.Or && tempBool))
{
break;
}
}
}
In the if you need ApplyCondition to be true and then set tempBool to true (also the result of ApplyCondition). In the else if you set tempBoolto the result of ApplyCondition. That means you can set tempBoolto the result of ApplyConditionin the first place. Now you just need to decide if you need to break.
Taking a more o-o approach, I think your operators need to be defined by classes that inherit from a base class. The base class would have an abstract Evaluate method that your operators implement. You can then use o-o polymorphism to evaluate your operators without worrying about the internal details. Effectively you have the beginnings of a simple interpreter.
A more formal way to code a boolean interpreter is considering a boolean expression as generated by a formal grammar and writing a parser and an interpreter for it. The interpreter could be implemented as an abstract syntax tree.
I made an open source library to achieve this, if you want you can take a look on GitHub.
I'm having some trouble with my console application.
I want to check the user input and execute something depending on what the user wrote. My code looks something like this:
if(Console.ReadLine() == "ADD")
{
//Add
}
else if (Console.ReadLine() == "LIST")
{
//DisplayList
}
else if (Console.ReadLine() == "SORT")
{
//Sort
}
else
{
//DisplayErrorMsg
}
Now when i type LIST in the console, i get a line-break, and I have to type LIST again to get expected behaviour, and all following else-if statements just add another line-break. (example below)
I've looked everywhere I can but I can't see what I've done wrong...
Please help!
SORT
SORT
SORT
//Sorting...
You are invoking ReadLine multiple times and therefore you read multiple times from the stdin. Try the following:
var line = Console.ReadLine();
if (line == "ADD")
{
//Add
}
else if (line == "LIST")
{
//DisplayList
}
else if (line == "SORT")
{
//Sort
}
else
{
//DisplayErrorMsg
}
Try to get line in a string, and so test the string.
string line = Console.ReadLine();
if (line == "ADD")
{
//Add
}
else if (line == "LIST")
{
//DisplayList
}
else if (line == "SORT")
{
//Sort
}
else
{
//DisplayErrorMsg
}
Every time you call Console.ReadLine() it will wait for user input.
Assign the value returned from running Console.ReadLine() to a variable.
Then do your if, else checks on that variable.
var userInput = Console.ReadLine();
if(userInput == "ADD")
{
//Add
}
else if (userInput == "LIST")
{
//DisplayList
}
else if (userInput == "SORT")
{
//Sort
}
else
{
//DisplayErrorMsg
}
string readfromConsole = Console.ReadLine()
if(readfromConsole == "ADD")
{
//Add
}
else if (readfromConsole == "LIST")
{
//DisplayList
}
else if (readfromConsole == "SORT")
{
//Sort
}
else
{
//DisplayErrorMsg
}
The problem you are having is that Console.readLine does exactly what it says it reads a new line. So what this change does is it saves the first read and compares against that instead of reading a new line each time. I hoped this helped
I have a piece of code where in I have an if block which when satisfied the flow goes into it and in there are nested if and else, if it does not satisfies any of the if block it should go into the else block but the problem i am facing is that it satisfies one if block and then goes into else as well. this is creating redundancy in my code.
it like this
if(condition = true)
{
if(condition1 == true)
{}
if(condition2 == true)
{}
else
{}
}
Now it satisfies condition 1 and then after performing if block operations goes into else also.
Please help. Code is in C#
You probably need something like this (notice else if with condition2):
if(condition)
{
if(condition1)
{}
else if(condition2)
{}
else
{}
}
You can skip '== true' in conditions.
get rid of the ==true's its just going to lead to a mistake like you made on the first line. also, add in else statements.
if (condition)
{
if (condition1)
{ }
else if (condition2)
{ }
else
{ }
}
As RaYell says, you need an extra "if" block. Here's a short but complete example to demonstrate:
using System;
public class Test
{
static void Main()
{
bool condition = true;
bool condition1 = true;
bool condition2 = false;
if (condition)
{
if (condition1)
{
Console.WriteLine("condition1");
}
// Note the "else if" here.
else if (condition2) {
Console.WriteLine("condition2");
}
else
{
Console.WriteLine("neither");
}
}
}
}
This prints "condition1" but not "neither".
If that isn't what you want, please clarify your question.
Put it like this
if(condition == true) {
if(condition1 == true) {}
else if(condition2 == true) {}
else {}
}
Ya you can use else if.Also you can write
if (condition==true) as if(condition) simply
For example
int i=2;
int j=3;
int k=4;
bool condition=k>1;
bool condition1=j<i;
bool condition2=j>i;
if (condition)
{
if (condition1)
{ }
else if (condition2)
{ }
else
{ }
}
Then, why don't you split up your code in methods, so you can do this:
if( condition)
{
if( condition1 )
{
DoSomethingForSituation1();
}
else
{
DoSomethingForSituation2();
}
}
else
{
DoSomethingForSituation1();
}
Also, when I look at it this way, you could say that 'condition' is redundant ?
Because either way, condition1 will always be true in some scenario ?
if( condition1 )
{
DoSomethingForSituation1();
}
else if( condition2 )
{
DoSomethingForSituation2();
}