Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I was wondering what was the most clean and understandable syntax for doing condition checks on nullable bools.
Is the following good or bad coding style? Is there a way to express the condition better/more cleanly?
bool? nullableBool = true;
if (nullableBool ?? false) { ... }
else { ... }
especially the if (nullableBool ?? false) part. I don't like the if (x.HasValue && x.Value) style ...
(not sure whether the question has been asked before ... couldn't find something similar with the search)
I think a lot of people concentrate on the fact that this value is nullable, and don't think about what they actually want :)
bool? nullableBool = true;
if (nullableBool == true) { ... } // true
else { ... } // false or null
Or if you want more options...
bool? nullableBool = true;
if (nullableBool == true) { ... } // true
else if (nullableBool == false) { ... } // false
else { ... } // null
(nullableBool == true) will never return true if the bool? is null :P
How about using GetValueOrDefault, which is pretty self-explaining and allows to use whatever default you want:
if (nullableBool.GetValueOrDefault(false)) {
}
You may not like it, but personally I find
if (x.HasValue && x.Value)
the most readable. It makes it clear you are working with a nullable type and it makes it clear you are first checking whether the nullable type has a value before acting on it conditionally.
If you take your version and replace the variable with x also it reads:
if (x ?? false)
Is that as clear? Is it obvious x is a nullable type? I'll let you decide.
Another way is to use constant pattern matching:
if (nullableBool is true) {}
if (nullableBool is false) {}
if (nullableBool is null) {}
Unlike the operator ==, when reading the code, this will distinguish the nullable type check from ordinary "code with a smell".
If you want to treat a null as false, then I would say that the most succinct way to do that is to use the null coalesce operator (??), as you describe:
if (nullableBool ?? false) { ... }
Just think of bool? as having 3 values, then things get easier:
if (someNullableBool == true) // only if true
if (someNullableBool == false) // only if false
if (someNullableBool == null) // only if null
Actually I think that (nullableBool ?? false) is a legitimate option especially when you are trying to evaluate a nullable bool in linq.
For example:
array.Select(v => v.nullableBool ?? false)
(from v in array where v.nullableBool ?? false)
Is cleaner in my opinion as opposed to:
array.Select(v => v.nullableBool.HasValue ? v.nullableBool.Value : false)
(from v in array where v.nullableBool.HasValue ? v.nullableBool.Value : false)
Use extensions.
public static class NullableMixin {
public static bool IsTrue(this System.Nullable<bool> val) {
return val == true;
}
public static bool IsFalse(this System.Nullable<bool> val) {
return val == false;
}
public static bool IsNull(this System.Nullable<bool> val) {
return val == null;
}
public static bool IsNotNull(this System.Nullable<bool> val) {
return val.HasValue;
}
}
Nullable<bool> value = null;
if(value.IsTrue()) {
// do something with it
}
Lets check how the comparison with null is defined:
static void Main()
{
Console.WriteLine($"null != null => {null != null}");
Console.WriteLine($"null == null => {null == null}");
Console.WriteLine($"null != true => {null != true}");
Console.WriteLine($"null == true => {null == true}");
Console.WriteLine($"null != false => {null != false}");
Console.WriteLine($"null == false => {null == false}");
}
and the results are:
null != null => False
null == null => True
null != true => True
null == true => False
null != false => True
null == false => False
So you can safely use:
// check if null or false
if (nullable != true) ...
// check if null or true
if (nullable != false) ...
// check if true or false
if (nullable != null) ...
If you only want to test for true against null/false, One I've just used and reads quite well is
bool? someCondition = null
if (someCondition.Equals(true))
...
I think its up to you. I certainly think the .HasValue approach is more readable, especially with developers not familiar with the ?? syntax.
The other point of a nullable boolean type is that it is tristate, so you may want to do something else when it is just null, and not default to false.
Given enum
public enum PublishMode { Edit, View }
you can do it like here
void MyMethod(PublishMode? mode)
{
var publishMode = mode ?? PublishMode.Edit;
//or
if (mode?? PublishMode.Edit == someValue)
....
}
If you're in a situation where you don't have control over whether part of the condition is checking a nullable value, you can always try the following:
if( someInt == 6 && someNullableBool == null ? false : (bool)someNullableBool){
//perform your actions if true
}
I know it's not exactly a purist approach putting a ternary in an if statement but it does resolve the issue cleanly.
This is, of course, a manual way of saying GetValueOrDefault(false)
Related
return ship.DefenseType?.PropulsionMethod != null
? new BattleMethod(ship.DefenseType.PropulsionMethod)
: null;
Hi, my current return statement, above, is returning a Propulsion method if it's not null. However, my database has different types of
propulsion methods denoted by the first 2 letters in the field(PK, PA, PT, etc).
How can I check to make sure that the PropulsionMethod starts with "PK" before going further into the return statement?
In pseudo code, it might look something like this:
if (ship.DefenseType?.PropulsionMethod).startsWith("PK")
&& ship.DefenseType?.PropulsionMethod != null)
{
return new BattleMethod(ship.DefenseType.PropulsionMethod)
}
else
{
return null;
}
I tried
return ship.DefenseType?.PropulsionMethod != null &&
ship.DefenseType?.PropulsionMethod.StartsWith("PK")
? new BattleMethod(ship.DefenseType.PropulsionMethod)
: null;
But I get this error:
operator && cannot be applied to operands of type bool and bool?
Just add this condition too:
return ship.DefenseType?.PropulsionMethod != null
&& ship.DefenseType?.PropulsionMethod.StartsWith("PK")
? new BattleMethod(ship.DefenseType.PropulsionMethod) : null;
As the operator is && so the second condition will be evaluated if the first one was true (not null in this case).
You can compare nullable bool directly with true:
return ship.DefenseType?.PropulsionMethod?.StartsWith("PK") == true
? new BattleMethod(ship.DefenseType.PropulsionMethod)
: null;
I have a List of objects in variable SanityResults with only one object whose values are null,I am trying to validate this condition as if (SanityResults != null) but fails?how to check for this case?
if (SanityResults != null)
{
//code
}
The condition that you are using will check whether SanityResults is null or not. But you wanted to check for the properties of all objects inside the list. So the better option is the use of Any() if you wanted to check check for any object inside the list is null means you have to use like the following:
if(SanityResults.Any(x => x == null))
{
// This will execute if any one of the object in the list is null
}
Now try this, if you wanted to check for properties of each object inside the list:
if(SanityResults.Any(x => x.failCount==null || x.htmllist ==null))
{
// include conditions like this for all required properties
// this statement will execute if any of the property of any of the objects in the list is null
}
Creating a separate method for is contain null
public bool IsContainNull(List<SanityResults> myList)
{
foreach(var myObject in myList)
{
if(myObject==null)
{return false;}
else{
foreach(PropertyInfo pi in myObject.GetType().GetProperties())
{
if(pi.PropertyType == typeof(string))
{
string stringValue = (string)pi.GetValue(myObject);
if(string.IsNullOrEmpty(stringValue ))
{
return true;
}
}
else if(pi.PropertyType == typeof(int))
{
int intValue = (int)pi.GetValue(myObject);
if(intValue==null)
{
return true;
}
}
}
}
return false;
}
}
Ok, just to throw another similar answer into the ring...
if (SanityResults == null || SanityResults.Any(sr => sr == null) ||
SanityResults.Any(sr => sr.failcount == null && sr.htmllist == null &&
sr.passcount == null && sr.testsuitename == null))
{
// Do something if the List is null, if any items in the list are null,
// or all of the properties of any item in the list are null
}
The problem is that the SanityResults is actually not null, and consists of one element with properties, that are null.
What elements are allowed to be null, and what aren't?
If none of the properties are allowed to be null, then go with this:
if(SanityResults.Any(x => x.failCount == null || x.passcount == null || x.testsuitename == null || x.htmllist == null))
{
// Code goes here
}
An element in the list, having nothing but null values in it, but having a semantic value in the code, smells a bit though.
There are three properties in the object
{obj.prop1, obj.prop2, obj.prop3} These properties are NULLABLE INTEGER
And I need to validate either all three properties should contain some value or all three properties are null.
Here's the validation
if (!((!obj.prop1.HasValue && !obj.prop2.HasValue && !obj.prop3.HasValue) ||
(obj.prop1.HasValue && obj.prop2.HasValue && obj.prop3.HasValue)))
{
//throw new Exception("");
}
Is there any better way to do it via some other Logical operators?
You can try this
if (obj.prop1.HasValue != obj.prop2.HasValue || obj.prop2.HasValue != obj.prop3.HasValue)
throw...
The expression above yields:
p1.HasValue p2.HasValue p3.HasValue
==========================================================================
false false false => false || false => false
false false true => false || true => true
false true false => true || true => true
true false false => true || false => true
false true true => true || false => true
true true false => false || true => true
true false true => true || true => true
true true true => false || false => false
You could use null coalescing for the null check, but you would still need to verify if all items do actually have a value for the other:
if((obj.prop1 ?? obj.prop2 ?? obj.prop3) == null
|| (obj.prop1.HasValue && obj.prop2.HasValue && obj.prop3.HasValue))
{
// conditional block
}
However, I think the original way you have it is more understandable to an average user.
I don't know of a logical operator that can make the code look nicer, but what I often do is wrap the functionality in to a method with a name that describes the test. This helps reduce the code size, and makes the code "self documenting".
Here's an example method that will test a bunch of objects to see if they are "partially null".
private static bool ArePartiallyNull(params object[] values)
{
if(values.Length <= 1)
return false;
var isNull = values[0] == null;
for(var i = 1;i < values.Length;i++)
{
if(isNull != (values[i] == null))
return true;
}
return false;
}
And this method in action: https://dotnetfiddle.net/6QIpDF
public class Program
{
public static void Main()
{
int? one = 1;
int? two = 1;
int? three = 1;
int? nullOne = null;
int? nullTwo = null;
int? nullThree = null;
Console.WriteLine(ArePartiallyNull(one, two, three));
Console.WriteLine(ArePartiallyNull(nullOne, nullTwo, nullThree));
Console.WriteLine(ArePartiallyNull(one, two, nullThree));
}
private static bool ArePartiallyNull(params object[] values)
{
if(values.Length <= 1)
return false;
var isNull = values[0] == null;
for(var i = 1;i < values.Length;i++)
{
if(isNull != (values[i] == null))
return true;
}
return false;
}
}
There are actually a handful of ways you can go about this depending on how "automatic" you want it to be when you add new properties for the object. If you don't mind updated your check each time you add a new property, I would just go with a simple method for comparison.
First, the example you have provided is a just fine approach. This is actually going to be the most performant way to perform the check. The downside is it is overly verbose, and doesn't scale well if you plan to add a lot more properties to the object.
The next method you could consider is to create a custom function that compares the properties for you. This way, when you use the function in your code, it is a bit less verbose. The function below will take as many int? variables you want to throw at it, and verify that they all either have a value, or don't have a value.
bool Test(params int?[] props)
{
bool? lastValue = null;
foreach(int? p in props)
{
// We haven't got a status yet so we just use the status for the first prop
if (lastValue.HasValue == false)
lastValue = p.HasValue;
else
{
// If the status of this next prop doesn't match the first, we know it is false
if (p.HasValue != lastValue.Value)
return false;
}
}
// Default back to true since we didn't identify any issues.
return true;
}
The last option I would propose would be to use reflection. With reflection, you could loop over the properties and check each one using similar logic to the function above. The benefit of this approach is that you do not need to adjust your logic as you add new properties. The downside is performance.
If you just want to make sure that all three have a value or don't have a value (regardless of what the value is) then
bool AllAreTrueOrFalse(params bool[] values)
{
return values.All(value=>value) || !values.Any(value=>value);
}
var allTrueOrFalse = AllAreTrueOrFalse(obj.prop1.HasValue, obj.prop2.HasValue,
obj.prop3.HasValue);
I have a very lengthy boolean variable which looks something like:
c.Card != null && slot.Card.CardId == c.Card.CardId && slot.E1Number == c.E1Number && slot.Capacity == c.Capacity && slot.PacketLinkCapacity == c.PacketLinkCapacity && slot.TrafficType == c.TrafficType && slot.TxFrequency == c.RxFrequency && slot.RxFrequency == c.TxFrequency && slot.E1Number != null && slot.Capacity != null && slot.ProtectionMode == c.ProtectionMode
Since this condition needs to be checked frequently I keep writing the same thing over and over again. Is it possible to store this in a variable so I can just reuse that whenever I need?
Yes, you can. Just create a method that does this check, or if you want to pass that function around, use Func<bool>:
Func<bool> f = new Func<bool>( () => YourLengthyMethod() );
Try something like this:
private static Expression<Func<Slot, bool>> Filter(filter)
{
return cat => [...your code for filtering...];
}
I would recommend you to separate this and write it to another method that you will call it when you want to do all these checks. It's not good practice to have repeated code in your project.
For example, in your case, you can give as parameters to this method the info (c.Card, slot.Card.CardId etc) and do the right checking over there.
Smart(ish) usage of C# features:
class EvaluatedBoolean
{
private readonly Func<bool> _evaluation = () => false;
public EvaluatedBoolean(Func<bool> evaluation)
{
_evaluation = evaluation;
}
public static implicit operator bool(EvaluatedBoolean eb)
{
return eb._evaluation.Invoke();
}
}
Then:
var eval = new EvaluatedBoolean(() => /*your conditions here*/);
...
PerformSomeWorkIfCondition(eval);
...
void PerformSomeWorkIfCondition(bool condition)
{
if (condition)
{
//do something
...
I have several bool checks against values. I wanted to check in ANY of the values return false then do something.
I attempted the follow:
bool formIsValid = true;
try{
Utility.testStringHasValue(txEmail.Text); <--- true
Utility.testStringHasValue(txFirstName.Text); <--- true
Utility.testStringHasValue(txLastName.Text); <--- FALSE
Utility.testStringHasValue(txUserEmployer.Text); <--- true
Utility.testStringHasValue(txUserPassword.Text); <--- true
Utility.testStringHasValue(txUserPassword2.Text); <--- true
}
catch (Exception)
{
formIsValid = false
}
.. any other solutions as this one does not at all!
UPDATE
I removed the Try/Catch completely and used:
bool isFormValid = Utility.testStringHasValue(txEmail.Text)
&& Utility.testStringHasValue(txFirstName.Text)
&& Utility.testStringHasValue(txLastName.Text)
&& Utility.testStringHasValue(txUserEmployer.Text)
&& Utility.testStringHasValue(txUserPassword.Text)
&& Utility.testStringHasValue(txUserPassword2.Text)
&& (txUserPassword.Text == txUserPassword2.Text);
Dont use exceptions for that scenario, when an exception is thrown there is a performance hit.
There is also a method available already to check if a string is entered ( String.IsNullOrEmpty )
You could use the && (and) operator to validate all fields are valid.
eg:
bool isValid = !String.IsNullOrEmpty(txtEmail.Text) && !String.IsNullOrEmpty(txtFirstname.Text) && !String.IsNullOrEmpty(txtLastName.Text);
Alternatively, you could flip it the other way using the || (or) operator
bool isInvalid = String.IsNullOrEmpty(txtEmail.Text) || String.IsNullOrEmpty(txtFirstname.Text) || String.IsNullOrEmpty(txtLastName.Text);
If you wrote the Utility methods, then I would suggest making sure it won't throw an exception, especially if it returns a boolean indicating whether the string has a value.
You could just do the following, and avoid the try { } catch { } entirely.
bool formIsValid = Utility.testStringHasValue(txEmail.Text); <--- true
&& Utility.testStringHasValue(txFirstName.Text); <--- true
&& Utility.testStringHasValue(txLastName.Text); <--- FALSE
&& Utility.testStringHasValue(txUserEmployer.Text); <--- true
&& Utility.testStringHasValue(txUserPassword.Text); <--- true
&& Utility.testStringHasValue(txUserPassword2.Text); <--- true
&& will not call evaluate the right side unless the left side returns true, so Utility.testStringHasValue will only actually be called 3 times in your example.
if ( Utility.testStringHasValue(txEmail.Text) &&
Utility.testStringHasValue(txFirstName.Text) &&
Utility.testStringHasValue(txLastName.Text) &&
Utility.testStringHasValue(txUserEmployer.Text) &&
Utility.testStringHasValue(txUserPassword.Text) &&
Utility.testStringHasValue(txUserPassword2.Text)
) {
all_good = true;
} else {
no_so_good = true;
}
Exception handling should not be used as control logic. It obfuscates the purpose.
That's because returning false doesn't throw an exception. You could always do:
if (!(
Utility.testStringHasValue(txEmail.Text) &&
Utility.testStringHasValue(txFirstName.Text) &&
Utility.testStringHasValue(txLastName.Text) &&
Utility.testStringHasValue(txUserEmployer.Text) &&
Utility.testStringHasValue(txUserPassword.Text) &&
Utility.testStringHasValue(txUserPassword2.Text)))
{
throw new Exception("Something is false");
}
if ( !(condtion1 && condition2 && .... && conditionN) )
{
// first condition evaluating to false gets you here
// anything afterwards is not checked.
}
Recode your Utility.testStringHasValue() to return false, not throw an exception.
Next
formIsValid= Utility.testStringHasValue(txEmail.Text) &&
Utility.testStringHasValue(txFirstName.Text) &&
Utility.testStringHasValue(txLastName.Text) &&
Utility.testStringHasValue(txUserEmployer.Text) &&
Utility.testStringHasValue(txUserPassword.Text) &&
Utility.testStringHasValue(txUserPassword2.Text) ;
if (formIsValid) {
//whatever
} else {
//whatever
}
What does testStringHasValue return? if a boolean then just use all the combined return values instead, like this :
boolean result = true;
result = result && Utility.testStringHasValue(txEmail.Text);
result = result && Utility.testStringHasValue(txFirstName.Text);
return result;
The way you are using exceptions is not very good. They should not be used for this kind of validation and your intention to reach the catch will only be valid if you actuelly throw a exception not onyl because it returns a boolean false value.
try..catch exception handling is more expensive than a simple boolean check, resource-wise. From the msdn site re: try..catch: "Catching exceptions at runtime creates additional overhead, and is likely to be slower than pre-checking to avoid exceptions."
Use if..then as shown previously.
Have you thought about writing a reusable method to check all the values passed to it aren't empty? Something like this could be a major time saver if you are using the code in multiple places:
using System.Linq;
public static class Utility
{
public static bool EnsureValuesNotEmpty(params string[] values)
{
return values.All(value => !string.IsNullOrWhiteSpace(value));
}
}
Then you can re-use the functionality with a lot less code, just pass all the values you want to check to it:
var formIsValid = Utility.EnsureValuesNotEmpty(txEmail.Text,
txFirstName.Text,
txLastName.Text,
txUserEmployer.Text,
txUserPassword.Text,
txUserPassword2.Text);