Should be a simple question for the C# experts here.
I basically want to check if one value or another is TRUE, a wild stab at the code is below:
if ((Boolean.Parse(staff.getValue("Male")) | Boolean.Parse(staff.getValue("Female")))
{
// is true
}
Is this correct?
Thanks
If EXACTLY ONE should be true then it is:
var male = bool.Parse(staff.getValue("Male"));
var female = bool.Parse(staff.getValue("Female"));
if (male ^ female)
{
//is true
}
Sounds like you're looking for the logical OR.
if(condition1 || condition2)
{
}
Use the || (double pipe), logical OR.
bool isMale = Boolean.Parse(staff.getValue("Male");
bool isFemale = Boolean.Parse(staff.getValue("Female");
if (isMale || isFemale) // note double pipe ||
{
// do something if true
}
In C# statement expressions are evaluated from left to right. In an OR operation, the second expression will not be evaluated if the first one equals true.
The conditional OR operator || is what you need
if ((Boolean.Parse(staff.getValue("Male")) || Boolean.Parse(staff.getValue("Female")))
{
//is true
}
If the first condition is TRUE, then the second condition isn't checked since the outcome is obviously going to return TRUE.
Note that TryParse works more fast and more safe then just Parse because doesn't throw an exception in case of error. TryParse returns bool that indicates was parse successful or was not.
So both parsing methods should return true and only after that - do the main check
bool male, female;
if ((Boolean.TryParse(staff.getValue("Male"), out male) &&
Boolean.TryParse(staff.getValue("Female"), out female)) &&
(male || female)) // or ^
{
// do stuff
}
or
bool male, female;
if (Boolean.TryParse(staff.getValue("Male"), out male) &&
Boolean.TryParse(staff.getValue("Female"), out female))
{
if(male) { }
else if (female) { } // or just else
}
else
{
// staff contains wrong data. Probably "yeap" instead of "true"
}
To indicate whether a gender is specified with a value of "true" rather than "false",
bool genderIsSpecified = staff.getValue("Male") | staff.getValue("Female");
.. will only determine whether it's one of those values, not which of those values the object staff is.
So, just in case this question is literal and not an abstract example, ...
Male or Female .. everyone is one or the other. Perhaps in your question you meant to ask which of the two is the case? In that case,
bool defaultGenderIfNoGenderDocumented = true; // male
bool MaleIfTrue_FemaleIfFalse = !string.IsNullOrEmpty(staff.getValue("Male"))
? bool.Parse(staff.getValue("Male"))
: string.IsNullOrEmpty(staff.getValue("Female"))
? bool.Parse(staff.getValue("Female"))
? false
: defaultGenderIfNoGenderDocumented
: defaultGenderIfNoGenderDocumented;
Or simply,
// assume value is properly populated, ignore "Female" value
bool isMale = bool.Parse(staff.getValue("Male"));
This is a similar scenario but I am checking for three or more bool values.
Thread th = new Thread(() =>
{
while (true)
{
bool allReadComplete = true;
foreach (IDataProvider provider in lstDataProviders)
{
provider.StartReading();
if (provider.FinishedReading)
allReadComplete = allReadComplete && provider.FinishedReading;
else
allReadComplete = provider.FinishedReading;
}
// to induce some context switching
Thread.Sleep(0);
if (allReadComplete)
break;
}
Console.WriteLine("Thread Exiting");
});
th.IsBackground = true;
th.Start();
A little exception checking is needed anyway. The Boolean.Parse() method gets a string as argument and returns either true or false only if the argument, once stripped out of whitespace, is equal to "True" or "False" (note capitalization). In ANY other case the function returns an exception.
Supposing that the possible values of staff.getValue("Male") and staff.getValue("Female") are exactly those two, then the simple disjunction (||) is sufficient. If any other return value is possible, including null and the empty string, then you have to check for exceptions
bool isMale;
try {
isMale = Boolean.Parse(staff.getValue("Male"));
} catch(Exception e) {
isMale = Boolean.False;
}
try {
isFemale = Boolean.Parse(staff.getValue("Female"));
} catch(Exception e) {
isFemale = Boolean.False;
}
if (isMale || isFemale) // note double pipe ||
{
// do something if true
}
or compare manually
bool isMale = Boolean.TrueValue == staff.getValue("Male");
bool isFemale = Boolean.TrueValue == staff.getValue("Female");
if (isMale || isFemale) // note double pipe ||
{
// do something if true
}
Related
I've got a Session that contains particular integer values, which are indexed with given controls. Normally, the following would work just fine:
int value;
int.TryParse(Session["Key"].ToString(), out value);
However, I do need to account for null. Where, if the string fails the default out would return a null. Except I noticed that int.TryParse doesn't work with:
int? value = null;
int.TryParse(Session["Key"].ToString(), out value);
So how can you try that parse, if fails it results in the null?
I found this question and the Microsoft Developer Network dictates:
When this method returns, contains the signed integer value
equivalent of the number contained in s, if the conversion succeeded,
or zero if the conversion failed. The conversion fails if the string
parameter is null or String.Empty, is not of the correct format, or
represents a number less than Min Value or greater than Max Value. This
parameter is passed uninitialized.
Which plainly states, if int.TryParse fails the integer will hold a value of zero. In the instance of my usage, zero could be a valid value. So I need null, any thoughts?
Sure; utilize the return value of int.TryParse (which returns if the conversion succeeded or not):
int? retValue = null;
int parsedValue = 0;
if (int.TryParse(Session["Key"].ToString(), out parsedValue))
retValue = parsedValue;
else
retValue = null;
return retValue;
A little verbose I'll admit, but you could wrap it in a function.
int tmp;
int? value = int.TryParse(Session["Key"].ToString(), out tmp) ? (int?)tmp : null;
The problem is the word "null." What does it mean? null could mean the value was indeterminable, an exception was thrown, simply that the value is null, or some other contextual meaning. Your question is a perfect example, because you, yourself, are arbitrarily stating that, in your opinion, null means the parsing of the string failed.
Microsoft's TryParse paradigm is great, but for limited usage. Consider these Scenarios:
string == "89"
string == null
string == "Hello World"
string == ""
string == "2147483650"
Yet, your only options are to assign an Integer or Null to your output, and to return true or false.
Assuming it worked, what are you going to do with that information? Something like this?
int? value = null;
if (int.TryParse(Session["Key"].ToString(), out value)) {
if (value == null)
// Handle "Appropriate" null
else
// Handle appropriate numeric value
}
else {
// Note: value == null here, and TryParse failed
// Handle null...
// What if the reason it failed was because the number was too big?
// What if the string was Empty and you wanted to do something special?
// What if the string was actually junk? Like "(423)322-9876" ?
// Long-Story Short: You don't know what to do here without more info.
}
Consider this NullableInt TryParse example:
public bool TryParseNullableInt(string input, out int? output)
{
int tempOutput;
output = null;
if (input == null) return true;
if (input == string.Empty) return true; // Would you rather this be 0?
if (!int.TryParse(input, out tempOutput))
return false; // What if string was "2147483650"... or "Twenty Three"?
output = tempOutput;
return true;
}
One solution is to use an enumeration TryParse instead of a boolean TryParse:
public ParseStatus TryParseNullableInt(string input, out int? output)
{
int tempInteger;
output = null;
if (input == null) return ParseStatus.Success;
if (input == string.Empty) { output = 0; return ParseStatus.Derived; }
if (!int.TryParse(input, out tempInteger)) {
if (ParseWords(input, out tempInteger)) { // "Twenty Three" = 23
output = tempInteger;
return ParseStatus.Derived;
}
long tempLong;
if (long.TryParse(input, out tempLong))
return ParseStatus.OutOfRange;
return ParseStatus.NotParsable;
}
output = tempInteger;
return ParseStatus.Success;
}
Another problem is the existence of the out variable. Your third option is to use a descriptive monad, something like this:
public Maybe<int?> TryParseNullableInt(string input)
{
if (input == null) return Maybe.Success(null);
if (input == string.Empty) { return Maybe.Derived(0); }
int tempInteger;
if (!int.TryParse(input, out tempInteger)) {
if (ParseWords(input, out tempInteger)) { // "Twenty Three" = 23
return Maybe.Derived(tempInteger);
}
long tempLong;
if (long.TryParse(input, out tempLong))
return Maybe.OutOfRange();
return Maybe.NotParsable();
}
return Maybe.Success(tempInteger);
}
You can use Monads as Single-Enumerable Values, or like so:
Maybe<int?> result = TryParseNullableInt("Hello");
if (result.HasValue) {
if (result.Status == ParseStatus.Success)
// Do something you want...
else if (result.Status == ParseStatus.Derived)
// Do something else... more carefully maybe?
}
else if (result.Status == ParseStatus.OutOfRange)
MessageUser("That number is too big or too small");
else if (result.Status == ParseStatus.NotParsable)
// Do something
With Monads, and possibly enumeration TryParses, you now have all the info you need from a descriptive return and nobody has to guess what null might mean.
I have looked for the answer to this question but could only find answers for the java language.
I have made a method in a class that returns either true or false,and if the method returns true,I want to use the true value in an if statement. I don't understand how to use the returned value.
Heres the method:
public bool endwall(Control player, Control endblock)
{
bool answer;
if (player.Right > endblock.Left && player.Left < endblock.Right - player.Width / 2 && player.Bottom > endblock.Top)
{
answer = true;
return answer;
}
else { answer = false; return answer; }
}
To summarize,I pretty much want to use answer in my main code(to write an if statement with it),but i'm not sure how to access it.
bool returnedValue = endwall(controlPlayer, controlEndblock);
if(returnedValue)
{
//code if returns true
}
else
{
//code if returns false
}
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;
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).
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 );