Comparing nullable ints - c#

In many places throught app I've seen stuffs like this:
(int)f.Status == something.Status
And this Status property is:
public int? Status { get; set; }
What I am trying to achieve is comparing nullable ints (int?) so that they are equal only if they both have a value and the value is the same. In particular, if they are both null I want them to be identified as not equal.
What is the best way to do that?

I'd suggest using:
f.Status == something.Status
assuming the two properties are either int or int?.
C# will allow you to compare int vs int? without an explicit cast.
For future readers, this answer was written prior to the OP making clear that comparing null to null was expected to return false.

This code is risky and it can give you NullReferenceException if f.Status is null.
You can check first if it has value -> f.Status.HasValue before casting to integer.
You can do this to prevent exception:
if (f.Status.HasValue && f.Status == something.Status)
{
}

I'd suggest rewriting condition into this:
f.Status.HasValue && something.Status.HasValue && f.Status == something.Status
It would prevent you from exceptions.
If any of statuses is just and int and not an int?, then you can omit HasValue check.
Already given answer suggests using simple ==, but it will return true in case both are nulls, opposite to suggested. You have to decide if that's desired behaviour.
As mentioned it could be simplified to
f.Status.HasValue && f.Status == something.Status
in case of both nulls result will be the same.

This question has already been answered, but here's another way of comparing nullable values.
if ((f.Status ?? 0) == something.Status){
//enter code here
}

Related

Implicit nullable cast inside if condition

I recently found some code with nullable if condition like this:
bool? nullableVariable;
//some lines of code involving nullableVariable
if (nullableVariable == true)
{
//some other lines of code
}
at first sight I thought it as potentially exception prone. My opinion was based on the fact that:
bool? nullableVariable = null;
bool variable = (bool)nullableVariable
would raise error System.InvalidOperationException: 'Nullable object must have a value.' and I expected that inside the if (nullableVariable == true) statement a cast of left operand from bool? to bool would be performed (my impression confirmed by the fact that moving cursor on == operator results in Visual Studio hint bool bool.operator == (bool left, bool right)).
Given that, I've been surprised seeing that:
bool? nullableVariable = null;
if (nullableVariable == true)
{
//some other lines of code
}
would not raise exception (skipping the code inside brackets).
So the question is: what is happening inside that if statement? maybe a hidden try-catch cast of left operand from bool? to bool with catch setting the result to false? or maybe right operand cast from bool to bool?? or something else?
See lifted operators in Nullable value types
I short, they are overloaded for comparisons like ==:
For the equality operator ==, if both operands are null, the result is
true, if only one of the operands is null, the result is false;
otherwise, the contained values of operands are compared.
So by comparing with true or false you can avoid handling the case that the nullable is null which makes the code more readable like in your example:
if (nullableVariable == true)
{
//some other lines of code
}
So whenever you compare(== or !=) a bool? with a bool the result is not a bool?(or null) but a bool with the rules described in the link above. That's why you can use it in the if.
As mentioned by others, the equality operators are lifted to the nullable equivalents.
There does seem to be slight differences in the way it is compiled. I'm not entirely sure why, but it may be to do with lack of compiler knowledge whether an operator is side-effecting for complex structs, whereas types like int and bool it knows what's going on.
Where A and B are nullables then,
A == B
This is compiled to the following for basic types like int:
(A.GetValueOrDefault() == B.GetValueOrDefault()) && (A.HasValue == B.HasValue)
And to this for more complex types:
(A.HasValue == B.HasValue) ? !A.HasValue || (A.GetValueOrDefault() == B.GetValueOrDefault())

OracleDataReader - Handling a NULL field value when setting up a default dropdown SelectedValue

I've got the following code:
// Here is where we will read in all our values and populate the form with them
lblBenCatX.Text = Convert.ToString(reader["Category"]);
lblBenProvX.Text = Convert.ToString(reader["Provision"]);
txtCommentBox.Text = Convert.ToString(reader["Feedback"]);
ddlDefect1.SelectedValue = Convert.ToString(reader["Network"]);
ddlIssue1.SelectedValue = Convert.ToString(reader["Issue_ID"]);
ddlResolution1.SelectedValue = Convert.ToString(reader["Resolution_ID"]);
ddlDefect2.SelectedValue = Convert.ToString(reader["Network2"]);
ddlIssue2.SelectedValue = Convert.ToString(reader["Issue_ID2"]);
ddlResolution2.SelectedValue = Convert.ToString(reader["Resolution_ID2"]);
The first 3 rows of code; no problem. However, if I have a record with a NULL value, the dropdowns break the code. So, I'm thinking I need to check the field first to make sure it's not NULL. Something like:
if (!Convert.ToString(reader["Network"]) = NULL)
{
ddlDefect1.SelectedValue = Convert.ToString(reader["Network"]);
}
However, that's giving me an error:
The left-hand side of an assignment must be a variable, property or
indexer
Any ideas? This is C# in VS2015 with an Oracle back end, if any of that matters.
In C#, you need to use two equal signs in a row == for equality comparison, not one. One equal sign = is an assignment operator.
if (first == second) { ... }
In your case, though, you would want to use the "not equals" != operator:
if (Convert.ToString(reader["Network"]) != null)
Which is cleaner and slightly more-efficent than this:
if (!(Convert.ToString(reader["Network"]) == null))
Note that I've wrapped the whole inner comparison in parens so the whole statement is being negated; otherwise, it will think you're trying to say !Convert.ToString(reader["Network"]), and, as you pointed out in the comments here, you can't use ! with a string.
That being said, if you're converting to string, then it's better to use string.IsNullOrEmpty() for checking:
if (!string.IsNullOrEmpty(reader["Network"].ToString())))
But the best is probably to just check if the column value is null, rather than converting it to string:
if (!reader.IsDBNull(["Network"]))
= is an assignment operator, used when setting values.
== is an equality operator, which determines whether something is equal to something else.
!= is also an equality operator, opposite to the one above. So, when something is not equal to something else.
So actually, you should be using != in this scenario:
if (Convert.ToString(reader["Network"]) != null)
{
ddlDefect1.SelectedValue = Convert.ToString(reader["Network"]);
}
You have a couple of choices. The first is to check if the value is DBNull which is different than an empty string/null value.
if (!reader.IsDBNull([ordinalPositionOfNetworkInSelectStatement]))
ddlDefect1.SelectedValue = Convert.ToString(reader["Network"]);
See IDataReader.IsDBNull. The only thing is that you need to know the ordinal position of the column you are checking.
The alternative is to check for dbnull in your sql select statement and use a function to return an empty string if it is. The positive side of this approach is you do not have to worry about checking for null in your c# code but I am not sure if it has any negative consequences in your oracle query or view. You can do this with COALESCE.
SELECT Category, Provision, Feedback, COALESCE(Network, '') AS Network /*other columns*/
FROM ... -- rest of the query
disclaimer - my oracle syntax is lacking but COALESCE does exist as a function

C# Null propagating operator / Conditional access expression & if blocks

The Null propagating operator / Conditional access expression coming in c#-6.0 looks like quite a handy feature. But I'm curious if it will help solve the problem of checking if a child member is not null and then calling a Boolean method on said child member inside an if block:
public class Container<int>{
IEnumerable<int> Objects {get;set;}
}
public Container BuildContainer()
{
var c = new Container();
if (/* Some Random Condition */)
c.Objects = new List<int>{1,2,4};
}
public void Test()
{
var c = BuildContainer();
//Old way
if ( null != c && null != c.Objects && c.Objects.Any())
Console.Write("Container has items!");
//C# 6 way?
if (c?.Object?.Any())
Console.Write("Container has items!");
}
Will c?.Object?.Any() compile? If the propagating operator short circuits (I assume that's the right term) to null then you have if (null), which isn't valid.
Will the C# team address this concern or am I missing the intended use case for the null propagating operator?
It won't work this way. You can just skip the explanation and see the code below :)
As you know ?. operator will return null if a child member is null. But what happens if we try to get a non-nullable member, like the Any() method, that returns bool? The answer is that the compiler will "wrap" a return value in Nullable<>. For example, Object?.Any() will give us bool? (which is Nullable<bool>), not bool.
The only thing that doesn't let us use this expression in the if statement is that it can't be implicitly casted to bool. But you can do comparison explicitly, I prefer comparing to true like this:
if (c?.Object?.Any() == true)
Console.Write("Container has items!");
Thanks to #DaveSexton there's another way:
if (c?.Object?.Any() ?? false)
Console.Write("Container has items!");
But as for me, comparison to true seems more natural :)
Null-conditional operator would return null or the value at the end of expression. For value types It will return result in Nullable<T>, so in your case it would be Nullabe<bool>. If we look at the example in the document for Upcoming Features in C# (specified here), it has an example:
int? first = customers?[0].Orders.Count();
In the above example, instead of int, Nullable<int> would be returned. For bool it will return Nullable<bool>.
If you try the following code in Visual Studio "14" CTP:
Nullable<bool> ifExist = c?.Objects?.Any();
The result of the above line would be a Nullable<bool>/bool?. Later you can do the comparison like:
Using null-coalescing operator ??
if (c?.Object?.Any() ?? false)
Using Nullable<T>.GetValueOrDefault Method
if ((c?.Objects?.Any()).GetValueOrDefault())
Using comparison against true
if (c?.Objects?.Any() == true)
var x = c?.Objects?.Any() is going to give you a nullable boolean, and as others have said, this means you can use an equality operator like this
x == true
or you can use null coalescing like this to have your result not be nullable
var x = c?.Objects?.Any() ?? false
But, personally, I think that 3-state (nullable) booleans are code smell. Even if this one is practically invisible, its existence should encourage you to think about what you are actually trying to do and determine if a nullable boolean is actually the way to go. In this case, I think that what you really want to do is something like this -
var objects = c?.Objects ?? Enumerable.Empty<Object>();
if (objects.Any())
{
...
}
Put that in an extension method and it will be even more succinct -
public static bool IsNullOrEmpty<T>(this IEnumerable<T> collection)
{
return !(collection ?? Enumerable.Empty<T>()).Any()
}

LINQ multiple and or condition

Im having trouble with my multiple AND/OR LINQ query
Current Error is "&& cannot be applied to bool and datetime"
Is there a better way to do this?
I think I may need to check for nulls on some of those too
Thanks
(d.Development != 1 && d.Deleted != 1 && d.Stock != 1) && (d.DecommissionDate = Convert.ToDateTime("1900-01-01"))
The second part doesn't convert to a boolean:
(d.DecommissionDate = Convert.ToDateTime("1900-01-01"))
= is an assignment operator. When it is done, it will try to compare a boolean to a DateTime. If your intent is to compare the DecommissionDate, use == instead. If you really want to assign it, you need to do it on a separate occasion.
You got a small typo: you used the single equals (=, used for assignment) instead of the double equals (==, equality).
Here's the fix:
d.DecommissionDate == Convert.ToDateTime("1900-01-01")

checking if a nullable bool is null or not [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Which is preferred: Nullable<>.HasValue or Nullable<> == null?
I know questions like this have been asked many times. But I never found an answer to how to check if a nullable bool is null or not.
Here is an answer I have to this:
bool? nullableBool;
if (nullableBool == true){
}else if (nullableBool == false){
}else{
}
But I was wondering if there is a better and more straight to the point way in order to minimize useless codes?
Thanks.
if (!nullableBool.HasValue)
{
// null
}
You also can directly compare it with null.
That's not a nullable bool, it's an unassigned bool and your code won't compile. You need to use bool? or Nullable<bool>.
bool? nullableBool = null; // or = true or = false
if (nullableBool.HasValue)
{
if (nullableBool.Value)
// true
else
// false
}
else
// null
Firstly, the bool you have used is not nullable. To create a nullable bool you can do one fo the following:
Nullable<bool> nullableBool;
or the shorthand version:
bool? nullableBool;
either of these can then be checked to see if it has a value using the following:
if(nullableBool.HasValue)
{
//nullableBool has been assigned a value
}
Your current approach is not recommended. If you need a nullable state then use a nullable bool. If you want to use a standard bool then be sure to assign it a value. I am surprised you don't get a compile error in Visual Studio with that code.
Try this plz:
if (!nullableBool.HasValue)
{
// your code
}

Categories

Resources