C# : Implicit conversion between '<null>' and 'bool' - c#

I got a weird error message when I tried to convert an object to bool, here is my code:
public partial class ModifierAuteur : DevExpress.XtraEditors.XtraForm
{
public ModifierAuteur(object getKeyDecesCheckBox)
{
decesCheckBox.Checked = getKeyDecesCheckBox == null ? null : (bool)getKeyDecesCheckBox;
}
}
and this is the error message :
Type of conditional expression cannot be determined because there is
no implicit conversion between <null> and bool

Assuming that the assignment is possible, you need to convert to a nullable bool, like this:
decesCheckBox.Checked = getKeyDecesCheckBox == null ? null : (bool?)((bool)getKeyDecesCheckBox);
The inner cast to bool unboxes the value, and the outer cast to bool? makes it compatible with null of the conditional expression.
If the left-hand side of the assignment does not allow nulls, you need to decide on the value to set when getKeyDecesCheckBox is null. Usually, that's a false:
decesCheckBox.Checked = getKeyDecesCheckBox == null ? false : (bool)getKeyDecesCheckBox;

Assuming the Checked property is of type nullable bool, I would probably do the following:
decesCheckBox.Checked = (getKeyDecesCheckBox == null ? (bool?)null : (bool?)getKeyDecesCheckBox);
If it takes a bool (not-nullable) you can convert the null to false easily with:
decesCheckBox.Checked = (getKeyDecesCheckBox == null ? (bool?)null : (bool?)getKeyDecesCheckBox).GetValueOrDefault();

decesCheckBox.Checked is of type bool. As such you must feed it either false or true.

Your '? :' operator has two possible incompatible return types: if the object is null, then it returns the value null, which can be cast to any nullable type. If the object is not null, then its return type is bool.
I don't know what type 'Checked' is, but I suspect that its type is 'bool'.
The problem here is that you can't cast null to the 'bool' type, and so you have to decide what type you want it to be in the case the object is null. If you wanted it to be false, you could write the statement as:
decesCheckBox.Checked = (getKeyDecesCheckBox as bool) ?? false;
The ?? Operator assigns the value 'false' in the case where the object is null, or cannot be converted to a bool.

Related

?? and ternary operations with Bool? and Guid? types

I am trying to check the state of an object, if it is null then I need to return null, otherwise, I need to return a Guid or a Bool.
Portrait_Enabled = _SiteImagesModel_ImagesViewModel == null ? null : _SiteImagesModel_ImagesViewModel.Enabled,
Portrait_PrimaryImage = _SiteImagesModel_ImagesViewModel.PrimaryImage ?? null,
Portrait_RecordID = _SiteImagesModel_ImagesViewModel.RecordID ?? null,
Portrait_RelatedImage = _SiteImagesModel_ImagesViewModel.RelatedImage ?? null,
I have tried both the ?? and the ? : and I get a compiler error stating:
Type of conditional expression cannot be determined because there is no implicit conversion between <null> and bool
Operator ?? cannot be applied to operands of type bool and <null>
Operator ?? cannot be applied to operands of type Guid and <null>
Both the Guid and Bool values are Nullable.
The MS Docs explanation about null-coalescing operator (note emphasized part):
A nullable type can represent a value from the type’s domain, or the
value can be undefined (in which case the value is null). You can use
the ?? operator’s syntactic expressiveness to return an appropriate
value (the right hand operand) when the left operand has a nullible
type whose value is null. If you try to assign a nullable value type
to a non-nullable value type without using the ?? operator, you will
generate a compile-time error. If you use a cast, and the nullable
value type is currently undefined, an InvalidOperationException
exception will be thrown.
Since the right-hand operand must return appropriate value of corresponding data type, it can't be set directly as null even the assigned variable has nullable data type (both operands must be have same data type).
Basically when you define a null-coalescing operator as this:
Portrait_PrimaryImage = _SiteImagesModel_ImagesViewModel.PrimaryImage ?? [DefaultValueIfNull];
It will translated as this:
Portrait_PrimaryImage = _SiteImagesModel_ImagesViewModel.PrimaryImage == null ? [DefaultValueIfNull] : _SiteImagesModel_ImagesViewModel.PrimaryImage;
Since both operands in ternary operator & null-coalescing operator must have same type, if you still want null value to be passed, you can cast the right-hand operand to proper type like this:
Portrait_PrimaryImage = _SiteImagesModel_ImagesViewModel.PrimaryImage ?? (bool?)null;
Portrait_RecordID = _SiteImagesModel_ImagesViewModel.RecordID ?? (Guid?)null;
Portrait_RelatedImage = _SiteImagesModel_ImagesViewModel.RelatedImage ?? (bool?)null;
Note that null is not at the same type as Nullable<bool>, you need to cast into bool? to get same data type.
As in your case, ternary operator usage just enough, no need to use null-coalescing operator when the second operand is null:
Portrait_Enabled = _SiteImagesModel_ImagesViewModel == null ? null : (bool?)_SiteImagesModel_ImagesViewModel.Enabled;
Portrait_RecordID = _SiteImagesModel_ImagesViewModel == null ? null : (Guid?)_SiteImagesModel_ImagesViewModel.RecordID;
Portrait_RelatedImage = _SiteImagesModel_ImagesViewModel == null ? null : (bool?)_SiteImagesModel_ImagesViewModel.RelatedImage;
References:
Type of conditional expression cannot be determined because there is no implicit conversion between 'int' and <null>
How to set null to a GUID property

Specified cast is not valid.(integer value in datatable)

I want to check the following field in the datatable against null :
r.Field<int>("prod_type")
if (r.Field<int>("prod_type") != null &&
!string.IsNullOrEmpty(r.Field<int>("prod_type").ToString()))
but I get the following exception :
Specified cast is not valid.
How to check the integer value in the datatable against null or empty ?
The Field extension method supports nullable types. Use HasValue to check if a nullable is not null:
if (r.Field<int?>("prod_type").HasValue)
The error you are getting is indicating that the field in the datatable is not of type int. If it is of type int it can't hold null value, instead you can try int? which is Nullable.
r.Field<int?>("prod_type") != null
If prod_type is indeed an int field in the database, try doing it like this:
if (r.Field<int?>("prod_type") != null)

Cast to Nullable in ternary operator C# creates new variable?

Assume that we have exression:
int? someValue = SomeCondition ? 1 : (int?)null;
so when SomeCondition is false,
(int?)null
evaluates and will be new instance of int? created at this time for assign to someValue?
When SomeCondition is false, the value of the ternary-operator expression will be null.
The (int?) before the null is just casting it (not creating a new object).
The cast is required since the compiler enforces that both possible return values of the expression be of the same type (or convertible to a common type). So in this case, the compiler sees that int (the type of the 1) and int? (the casted type of the null) are convertible to (int?). Without the cast, the compiler has no way of reconciling null and int since value types cannot be null, and null has no natural type of its own.
You could also apply the (int?) cast to the 1 to achieve the same effect.

C# Handling Null Values

I have CustomerID declared as
int? CustomerID=null;
I am checking null values while reading DataReader
Id = reader["CustomerId"] is DBNull ? null :Convert.ToInt32(reader["CustomerID"]);
It is throwing
Type of conditional expression cannot be determined because there
is no implicit conversion between '<null>' and 'int'
What is the problem with the Conversion?
I think you need to do it this way:
if(! reader.IsDBNull(reader.GetOrdinal("CustomerId"))
{
Id = Convert.ToInt32(reader["CustomerID"]);
}
else
{
Id = NULL;
}
You need to use the .IsDBNull method on the reader to determine ahead of time if a column is NULL - if it is, don't even read the value from the reader.
Change your conditon to
reader["CustomerId"] == DBNull.Value
A ?: conditional expression cannot evaluate to two different types on the true and false condition. I think a cast (int?)null should work.
The problem (assuming that Id is declared properly) is that the conditional statement infers the result type from the true result. In your case, that type is null. It then will try to cast the second type to the same as the first...and there is no cast from int to null.
The solution is to cast the true expression to the desired type:
Id = reader["CustomerId"] == DBNull.Value ?
(int?) null :
Convert.ToInt32(reader["CustomerID"]);
Try this
Id = reader["CustomerId"] is DBNull ? (int?)null : Convert.ToInt32(reader["CustomerID"]);
the types of both parts of the ?: need to be explicit
What's happening is your code is incorrectly evaluating and trying to do the Convert function.
Its readding reader["CustomerId"] is DBNull which it isn't its really a DBNull.Value so then it attempts to do Convert.ToInt32("<null>") and crashes. You need to fix your if statement, and add a (int ?) cast.
It should be:
Id = reader["CustomerId"] is DBNull.Value ? (int?) null :Convert.ToInt32(reader["CustomerID"]);

Why can't I use '??' operand for System.DBNull value?

I have an Oracle data table fetching columns that be null. So I figure to keep the code nice and simple that I'd use the ?? operand. AlternatePhoneNumber is a string in my C# model.
AlternatePhoneNumber = customer.AlternatePhoneNumber ?? ""
However, even with that code I still get the error.
System.InvalidCastException: Unable to cast object of type 'System.DBNull' to type 'System.String'.
I know what the error means but why is ?? not usable on DBNull? Isn't null and DBNull essentially the same?
Thank you.
The ?? operator only applies to actual nulls.
null and DBNull.Value are not the same; DBNull.Value is simply a placeholder object.
Also, that exception is coming from inside the AlternatePhoneNumber property, before your ?? operator executes. (Your code doesn't have a cast).
If customer is a row in a typed dataset, change the column's NullValue property in the designer.
null and DBNull are not the same. System.DBNull is an actual object.
The problem is that AlternatePhoneNumber is a string. DBNull is not.
Try this instead:
AlternatePhoneNumber = (customer.AlternatePhoneNumber as string) ?? ""
Do this:
public T IfNull<T>(object o, T value)
{
return (o == DbNull.Value) ? value : (T)o;
}
DBNull is a type with a single value, and is not the same as a null string reference, which is why you can't use ??. You could do this however:
string alternativePhoneNumber = DBNull.Value.Equals(customer) ? string.Empty : ((Customer)customer).AlternatePhoneNumber;
As other replies state, null means a reference that refers to no object, while DBNull is a class supplied by ADO.NET to indicate when a field or value is NULL at the database (or in a DataTable).
While you can use the conditional (ternary) operator (?:) to do what you want:
AlternatePhoneNumber = customer.AlternatePhoneNumber is DBNull
? ""
: customer.AlternatePhoneNumber;
I tend to wrap this up in an extension method:
static class NullExtensions
{
public static T WhenNull<T>( this object value, T whenNullValue )
{
return (value == null || value is DBNull)
? whenNullValue
: (T)value;
}
}
which I find makes the code easier to read and understand.
AlternatePhoneNumber = customer.AlternatePhoneNumber.WhenNull( "" );
DBNull is NOT a real "null".
The "??" - operator detects only null - references, not objects that emulate "null" behavior.

Categories