double number;
bool isParsed = false;
while(!isParsed)
{
Console.WriteLine("Enter the value");
isParsed = double.TryParse(Console.ReadLine(), out number);
if(isParsed)
{
break;
}
Console.WriteLine("Invalid value");
}
A friend and I were studying this code block. I found this part to understand:
bool isParsed = false;
while(!isParsed)
I thought that if isParsed = false, and the while loop will check the negation (!isParsed) to see if it should run, wouldn't this be the logic:
while(!isParsed) => while(NOT(false)) => while (true)?
Therefore, the while loop would never run. But it does run. Later I understood that a check was happening:
while (!isParsed) => while((!isParsed) == true),
but he says that not exactly what is happening.
Can someone explain what is happening here?
You're saying it correctly: while (true). That true boolean condition denotes that the next (and first) iteration will run.
!false == true
Take a look at the MSDN documentation stating the behavior of the while loop: https://msdn.microsoft.com/en-us/library/2aeyhxcd.aspx
When using a boolean in an expression you are checking for a value of true. When adding the logical NOT operator, you are now looking for a value of false.
while (false)
bool isParsed = false;
while(!isParsed)
Loop should run, at least once; Which is correct behavior, since your condition is evaluating to true.
Related
I have a report that uses parameters to hide or show data on a chart at runtime. I have the following code to read the parameter and use it to control the visibility of the axes.
((SplineSeriesView)xrChart1.Series[0].View).AxisY.Visible = Convert.ToBoolean(this.Parameters[0].Value);
((SplineSeriesView)xrChart1.Series[1].View).AxisY.Visible = Convert.ToBoolean(this.Parameters[1].Value);
((SplineSeriesView)xrChart1.Series[2].View).AxisY.Visible = Convert.ToBoolean(this.Parameters[2].Value);
((SplineSeriesView)xrChart1.Series[3].View).AxisY.Visible = Convert.ToBoolean(this.Parameters[3].Value);
((SplineSeriesView)xrChart1.Series[4].View).AxisY.Visible = Convert.ToBoolean(this.Parameters[4].Value);
((SplineSeriesView)xrChart1.Series[5].View).AxisY.Visible = Convert.ToBoolean(this.Parameters[5].Value);
Because series 0 and series 1 are both tied to the same axis, I am using an or operator. The problem that I am having is that the axis will not hide when they are both false. This is the code that I am using:
bool zero = Convert.ToBoolean(this.Parameters[0].Value);
bool one = Convert.ToBoolean(this.Parameters[1].Value);
if ((zero = true)||(one = true))
{
((SplineSeriesView)xrChart1.Series[0].View).AxisY.Visible = true;
}
else if ((zero = false) && (one = false))
{
((SplineSeriesView)xrChart1.Series[0].View).AxisY.Visible = false;
}
How can I get the axis to hide? Thank you in advance for your help.
It's important to remember the difference between equality comparison == and the settor operator =. In your if statement, you're using the settor, and want to be using the comparison.
If you use the proper operator, your code could look like this, and that should solve your issue:
if ((zero == true)||(one == true))
{
((SplineSeriesView)xrChart1.Series[0].View).AxisY.Visible = true;
}
else if ((zero == false) && (one == false))
{
((SplineSeriesView)xrChart1.Series[0].View).AxisY.Visible = false;
}
The reason you were having problems is that you were using the settor, which was automatically setting zero and one to true. Thus, the program was evaluating your if statement as: "if (true or true)", which is always true. This is why setting the values to false wasn't working.
Incidentally, there are a few things you could've done to avoid this mistake. First, your compiler should have warned you that you weren't using an equality operator. Second, you could get in the habit of putting constants first: if (false = zero) would generate a compile-time error. (Personally, I really don't like that coding style, it doesn't read cleanly to me, but your mileage may vary.)
I'd rewrite your statements to be a lot cleaner, but functionally equivalent:
if (zero || one)
{
((SplineSeriesView)xrChart1.Series[0].View).AxisY.Visible = true;
}
else
{
((SplineSeriesView)xrChart1.Series[0].View).AxisY.Visible = false;
}
When you're putting boolean variables in to an if statement, there's no good reason to compare them to boolean constants. Your second if isn't necessary at all, since it's the only case that can happen if the first one doesn't. (i.e. "if !(zero || one)" === "!zero && !one" - it's called DeMorgan's Rule.)
In fact, your whole if statement can be condensed down to one clear line:
((SplineSeriesView)xrChart1.Series[0].View).AxisY.Visible = zero || one;
I think that your problem was in using '=' instead of '=='. The expression zero = true sets zero to true and this true value is used as expression value. So, after first condition checking 'zero' always becomes true and 'else' branch never executes because 'zero' is no longer false.
In fact, expression zero == true is equal to just zero, so you can simplify your condition:
bool zero = Convert.ToBoolean(this.Parameters[0].Value);
bool one = Convert.ToBoolean(this.Parameters[1].Value);
if (zero || one) // true if 'zero' or 'one' is true
{
((SplineSeriesView)xrChart1.Series[0].View).AxisY.Visible = true;
}
else // goes here if both 'zero' and 'one' is false
{
((SplineSeriesView)xrChart1.Series[0].View).AxisY.Visible = false;
}
Or even
bool zero = Convert.ToBoolean(this.Parameters[0].Value);
bool one = Convert.ToBoolean(this.Parameters[1].Value);
bool axisVisible = zero || one;
((SplineSeriesView)xrChart1.Series[0].View).AxisY.Visible = axisVisible;
A simple C# code
bool result;
if (bool.TryParse("false", out result) && result)
{
Console.WriteLine(result);
}
and
bool result;
if (bool.TryParse("tRue", out result) && result)
{
Console.WriteLine(result);
}
Resharper says that result in Console.WriteLine(result) is always true. Why?
It's due to the && result part - you'll only ever get into the body of the statement if result is true. How do you anticipate any way of getting in there with result being false?
What Reharper is telling you is that, if you are doing
Console.WriteLine(result);
you might as well do
Console.WriteLine(true);
That is, anywhere you use result within the if, you can as well use true, as, if result were false, the you would not have reached the body of the if.
Because if(true && false) (thats what you get, when you resolve the parsing) will never enter the if body. Thats what you are parsing in the first example.
Which is better of the following?
this.isLoggedIn = (bool)HttpContext.Current.Session["li"] == true;
or
this.isLoggedIn = (bool)HttpContext.Current.Session["li"];
It needs be to true ONLY when the session is true. If the session is set to false will this evaluate to true in #2 as it exists? Or is it evaluating its value?
The second one:
this.isLoggedIn = (bool)HttpContext.Current.Session["li"];
(bool)HttpContext.Current.Session["li"] is already a boolean (so will be either true or false), so no need for the extra comparison and return value of the boolean expression.
Either way, you need to check that the li session variable exists before trying to cast it, or your code will throw (I think a NullReferenceException).
The latter is clearer, IMO. They're functionally equivalent though - in both cases, it will fetch the value of "li" from the session and attempt to cast it to bool, throwing an exception if the value isn't present.
Create a property for the desired value:
public bool IsLoggedIn {
get { return (bool)HttpContext.Current.Session["li"]; }
}
You could even go one extra level, if the session is used a lot in the class:
public bool IsLoggedIn {
get { return (bool)Session["li"]; }
}
private HttpSessionState Session {
get { return HttpContext.Current.Session; }
}
Also, if you ever want to look at the session by itself, use a better key, like "IsLoggedIn", instead of "li".
It might be good to create a special class for these application-wide values:
public static class MyAppSession {
const string IsLoggedInKey = "IsLoggedIn";
public static bool IsLoggedIn {
get {
return Session[IsLoggedInKey] != null && (bool)Session[IsLoggedInKey];
}
internal set { Session[IsLoggedInKey] = value; }
}
// ...
private static HttpSessionState Session {
get { return HttpContext.Current.Session; }
}
}
The first and the second approach is equivalent, but the first one is to verbose for my taste. I like the second one much better.
Just as I like this
bool accepted = true;
if( accepted)
{
..
}
Better than
bool accepted = true;
if( accepted == true)
{
..
}
I feel it clearer that way if the variables are properly named.
Just put the expected value in the place of the expression, and it will become pretty clear:
First example:
Before: this.isLoggedIn = (bool)HttpContext.Current.Session["li"] == true;
After: this.isLoggedIn = true == true;
Second example:
Before: this.isLoggedIn = (bool)HttpContext.Current.Session["li"];
After: this.isLoggedIn = true;
Now, try the same for the false case:
First example:
Before: this.isLoggedIn = (bool)HttpContext.Current.Session["li"] == true;
After: this.isLoggedIn = false == true;
Second example:
Before: this.isLoggedIn = (bool)HttpContext.Current.Session["li"];
After: this.isLoggedIn = false;
As you can see, there will be no difference in the result between the two approaches. It all comes down to questions about coding style and readability, where I would guess that you would find a bias towards the shorter version.
You never need to write code that says:
bool x = (y == true);
Instead just use
bool x = y;
In your specific case you should use:
this.isLoggedIn = HttpContext.Current.Session["li"] != null
&& (bool)HttpContext.Current.Session["li"];
This way you will not get an exception if Session["li"] has not been assigned yet. However you will get an exception if Session["li"] is not castable to bool.
I would use the second option with a variant:
this.isLoggedIn = (bool) (HttpContext.Current.Session["li"] ?? "false");
The ?? is null-coalescing operator - it gives a value of "false" to the expression on its lefthand side, in case it happens to be null.
Both pieces of code are equal, so the better is the second (it's shorter).
While doing this bool iteration, I was tempted to use the non existing operator ||=, and figured there must be a simpler or better design that would replace its valid use (rather than think it's just "missing"):
bool validExtension = false;
foreach (string extension in Plugin.Extensions)
{
validExtension = validExtension || Path.GetExtension(file).Equals(extension.TrimStart('*'), StringComparison.InvariantCultureIgnoreCase);
if (validExtension)
{
break;
}
}
importButton.Enabled = File.Exists(importTextBox.Text) && validExtension;
That loop has an invariant: on entry to the body, validExtension = false.
So the body can be simplified to:
if (validExtension = Path.GetExtension(file).Equals(extension.TrimStart('*'), StringComparison.InvariantCultureIgnoreCase))
break;
If there wasn't such an invariant, you could use the compound assignment operator |= if you always wanted to evaluate the right-hand side, or if (!lhs) lhs = rhs; if you wanted short-circuiting.
foreach (string extension in Plugin.Extensions)
{
if (Path.GetExtension(file).Equals(extension.TrimStart('*'), StringComparison.InvariantCultureIgnoreCase))
{
validExtension = true;
break;
}
}
This works because you are breaking the first time you find a valid extension, so validExtension is always false on the first line of the loop.
can't you just say validExtension = Path.Get.... since at the start of the expression validExtension will always be false.
While there is no ||= operator in C#, there is the |= operator that may be what you're looking for.
MSDN Reference
If its a string[], the whole code can be changed like this
Func<string[], string, bool> validExtension = (arr, s) => arr.Contains(s);
importButton.Enabled = validExtension(Plugin.Extensions, Path.GetExtension(file)) && File.Exists(importTextBox.Text);
For checking a value inside an Array you could always use Array.Contains extension method.
P.S: I have reversed the tests as Ben Voigt rightfully said
I came across the following expression in someone else's code. I think it's terrible code for a number of reasons (not least because it fails to take into account bool.TrueString and bool.FalseString), but am curious as to how the compiler will evaluate it.
private bool GetBoolValue(string value)
{
return value != null ? value.ToUpper() == "ON" ? true : false : false;
}
Edit
Incidentally, aren't the expressions evaluated from the inside-outwards? In this case, what's the point of checking for value != null after the call to value.ToUpper() which will throw a null reference exception?
I think the following is a correct (deliberately) verbose version (I'd never leave it like this :D ):
if (value != null)
{
if (value.ToUpper() == "ON")
{
return true;
}
else // this else is actually pointless
{
return false;
}
}
else
{
return false;
}
Which can be shortened to:
return value != null && value.ToUpper == "ON";
Is this a correct re-writing of the expression?
It looks like the method is indended to handle a value that comes from a checkbox HTML element. If no value is specified for the checkbox, it uses the value "on" by default. If the checkbox is not checked there is no value at all from it in the form data, so reading the key from Request.Form gives a null reference.
In this context the method is correct, althought it's quite horrible due to the use of the if-condition-then-true-else-false anti-pattern. Also it should have been given a name that is more fitting for it's specific use, like GetCheckboxValue.
Your rewrite of the method is correct and sound. As the value is not culture dependant, converting the value to uppercase should not use the current culture. So a rewrite that is even slightly better than the one that you proposed would be:
return value != null && value.ToUpperInvariant == "ON";
(The culture independent methods are also a bit faster than the ones using a specific culture, so there is no reason not to use them.)
Incidentally, aren't the expressions
evaluated from the inside-outwards?
If it was method calls so that all expressions were actually evaluated, they would, as the inner call has to be made to evaluate the parameters for the outer call.
However, the second and third operands of the conditional expression is only evaluated if they are used, so the expressions are evaluated from the outside and inwards. The outermost condition is evaluated first to decide which of the operands it will evaluate.
You are correct, both in your rewriting and in your assertion that this attempt at conciseness is bad because it leads to confusion.
well the first one is a double-nested ternary operator
return (value != null) ? [[[value.ToUpper() == "ON" ? true : false]]] : false;
The bit in [[[ ]]] is the first result of the ternary expression which gets evaluated
when the first condition is true so you're reading/assertion of it is correct
but its ugly as hell and very unreadable/unmaintainable in its current state.
I'd definitely change it to your last suggestion
SideNote:
People who do
if(X == true)
return true;
else
return false;
instead of
return X;
should be taken out and shot ;-)
Are you looking for speed or readability and organization? Speed of execution, your shortened example is probably the best way to go.
For a few extra milliseconds, you could re-write this utility method as an extension method like so:
public static bool ToBoolean(this string value)
{
// Exit now if no value is set
if (string.IsNullOrEmpty(value)) return false;
switch (value.ToUpperInvariant())
{
case "ON":
case "TRUE":
return true;
}
return false;
}
... and then you would use it as follows:
public static void TestMethod()
{
bool s = "Test".ToBoolean();
}
EDIT:
Actually, I'm wrong... a quick performance test shows that the extension method is FASTER than the inline method. The source of my test is below, as well as the output on my PC.
[Test]
public void Perf()
{
var testValues = new string[] {"true", "On", "test", "FaLsE", "Bogus", ""};
var rdm = new Random();
int RunCount = 100000;
bool b;
string s;
Stopwatch sw = Stopwatch.StartNew();
for (var i=0; i<RunCount; i++)
{
s = testValues[rdm.Next(0, testValues.Length - 1)];
b = s.ToBoolean();
}
Console.Out.WriteLine("Method 1: {0}ms", sw.ElapsedMilliseconds);
sw = Stopwatch.StartNew();
for (var i = 0; i < RunCount; i++)
{
s = testValues[rdm.Next(0, testValues.Length - 1)];
b = s != null ? s.ToUpperInvariant() == "ON" ? true : s.ToUpperInvariant() == "TRUE" ? true : false : false;
}
Console.Out.WriteLine("Method 2: {0}ms", sw.ElapsedMilliseconds);
}
Output:
Method 1: 21ms
Method 2: 30ms
I read the original expression the same way you do. So I think your shortened expression is correct. If value is null it will never get to the second conditional, so it looks safe to me.
I also hate the constructs like:
if (value.ToUpper() == "ON")
{
return true;
}
else // this else is actually pointless
{
return false;
}
as you noticed it is a long and convoluted (not to say stupid) way of writing:
return value.ToUpper() == "ON";
Your proposition is nice, short and correct.
Another alternative:
return string.Equals( value, "ON", StringComparison.OrdinalIgnoreCase );