using the ?? operator and dealing with a null value - c#

I am returning a scalar value from a SQL Server 2008 database:
string reason = cmd.ExecuteScalar().ToString() ?? : "";
I want to make sure that if null is returned, that reason = "" and not null.
i am getting an error on this line:
Error 3 Invalid expression term ':'
How can this be fixed?
EDIT:
thank you for the changes on the colon, now i am getting this exception on the same line:
string reason = cmd.ExecuteScalar().ToString() ?? "";
System.NullReferenceException occurred
Message="Object reference not set to an instance of an object."

Try this:
string reason = cmd.ExecuteScalar().ToString() ?? "";
BUT: this will still fail, since if .ExecuteScalar() returns a NULL, you're already causing a Null Reference Exception by calling .ToString() on that NULL value......
So I guess the ?? operator really doesn't help you here... do the "usual" dance:
object result = cmd.ExecuteScalar();
if(result != null)
{
reason = result.ToString();
}
else
{
reason = "(NULL value returned)";
}

First, you shouldn't have the : when using the ?? operator.
Second, to do what you are trying to do here without getting an error, you need to do it differently:
object objReason = cmd.ExecuteScalar();
string reason = objReason == null ? "" : objReason.ToString();
This will check whether or not your returned value is null and if it is, the second line will set reason to a blank string, otherwise it will use your returned value.

Since ExecuteScalar() returns object that might be null you should not call .ToString() since that may throw and exception.
string reason = Convert.ToString(cmd.ExecuteScalar());
This works because Convert.ToString() will convert null to string.Empty
or if you must use ?? because you really like it:
(cmd.ExecuteScalar() ?? (object)"").ToString();

Just get rid of the colon.
string reason = cmd.ExecuteScalar().ToString() ?? "";
For reference, check the MSDN page.

When using the null-coalescing operator, you don't need the colon:
string reason = cmd.ExecuteScalar().ToString() ?? "";
As others have pointed out though, ToString() would cause a NullReferenceExcpetion to be thrown anyway...so you don't gain anything here. You'd be much better off splitting this into multiple lines:
var result = cmd.ExecuteScalar();
string reason = result == null ? "" : result.ToString();

You're confusing the ? conditional operator, the syntax for which looks like this:
String x = condition ? valueIfConditionIsTrue : valueIfConditionIsFalse;
with the ?? null-coalesce operator whose syntax is as follows:
String x = possiblyNull ?? valueIfPossiblyNullIsNull;
So, apart from all that... this is the part you really want:
String reason = (cmd.ExecuteScalar() ?? "").ToString();
This takes care of your exception where ToString() was causing a null-reference exception.

Just use
string reason = cmd.ExecuteScalar() ?? "";

Related

LINQ: Nullable object must have a value [duplicate]

There is paradox in the exception description:
Nullable object must have a value (?!)
This is the problem:
I have a DateTimeExtended class,
that has
{
DateTime? MyDataTime;
int? otherdata;
}
and a constructor
DateTimeExtended(DateTimeExtended myNewDT)
{
this.MyDateTime = myNewDT.MyDateTime.Value;
this.otherdata = myNewDT.otherdata;
}
running this code
DateTimeExtended res = new DateTimeExtended(oldDTE);
throws an InvalidOperationException with the message:
Nullable object must have a value.
myNewDT.MyDateTime.Value - is valid and contain a regular DateTime object.
What is the meaning of this message and what am I doing wrong?
Note that oldDTE is not null. I've removed the Value from myNewDT.MyDateTime but the same exception is thrown due to a generated setter.
You should change the line this.MyDateTime = myNewDT.MyDateTime.Value; to just this.MyDateTime = myNewDT.MyDateTime;
The exception you were receiving was thrown in the .Value property of the Nullable DateTime, as it is required to return a DateTime (since that's what the contract for .Value states), but it can't do so because there's no DateTime to return, so it throws an exception.
In general, it is a bad idea to blindly call .Value on a nullable type, unless you have some prior knowledge that that variable MUST contain a value (i.e. through a .HasValue check).
EDIT
Here's the code for DateTimeExtended that does not throw an exception:
class DateTimeExtended
{
public DateTime? MyDateTime;
public int? otherdata;
public DateTimeExtended() { }
public DateTimeExtended(DateTimeExtended other)
{
this.MyDateTime = other.MyDateTime;
this.otherdata = other.otherdata;
}
}
I tested it like this:
DateTimeExtended dt1 = new DateTimeExtended();
DateTimeExtended dt2 = new DateTimeExtended(dt1);
Adding the .Value on other.MyDateTime causes an exception. Removing it gets rid of the exception. I think you're looking in the wrong place.
When using LINQ extension methods (e.g. Select, Where), the lambda function might be converted to SQL that might not behave identically to your C# code. For instance, C#'s short-circuit evaluated && and || are converted to SQL's eager AND and OR. This can cause problems when you're checking for null in your lambda.
Example:
MyEnum? type = null;
Entities.Table.Where(a => type == null ||
a.type == (int)type).ToArray(); // Exception: Nullable object must have a value
Try dropping the .value
DateTimeExtended(DateTimeExtended myNewDT)
{
this.MyDateTime = myNewDT.MyDateTime;
this.otherdata = myNewDT.otherdata;
}
Assign the members directly without the .Value part:
DateTimeExtended(DateTimeExtended myNewDT)
{
this.MyDateTime = myNewDT.MyDateTime;
this.otherdata = myNewDT.otherdata;
}
In this case oldDTE is null, so when you try to access oldDTE.Value the InvalidOperationException is thrown since there is no value. In your example you can simply do:
this.MyDateTime = newDT.MyDateTime;
Looks like oldDTE.MyDateTime was null, so constructor tried to take it's Value - which threw.
I got this message when trying to access values of a null valued object.
sName = myObj.Name;
this will produce error. First you should check if object not null
if(myObj != null)
sName = myObj.Name;
This works.
I got this solution and it is working for me
if (myNewDT.MyDateTime == null)
{
myNewDT.MyDateTime = DateTime.Now();
}

c# trouble getting a null-coalescing operator ?? to work

I have read several articles and questions on Stack Overflow and still cannot see what I am doing wrong. Not using C#6 -- sorry for not posting that at first. VS 2013.
This code works:
if (row.Cells["CSR_Notes"].Value != null)
{
deliveryEvent.CSR_Notes = row.Cells["CSR_Notes"].Value.ToString();
}
and this code works:
deliveryEvent.CSR_Notes = row.Cells["CSR_Notes"].Value != null
? row.Cells["CSR_Notes"].Value.ToString() : "";
But this code throws a "Object reference not set..." error if the value is null.
deliveryEvent.CSR_Notes = row.Cells["CSR_Notes"].Value.ToString() ?? "";
What am I missing?
The issue is that Value is the potentially null property. By calling the ToString() method on it, you are creating the Null Reference Exception before the null coalescing operator has a chance to be used. You can fix this with the Null Propagating Operation from C# 6, like so:
deliveryEvent.CSR_Notes = row.Cells["CSR_Notes"].Value?.ToString() ?? "";
Notice the ? after Value. This is the Null Propagating operator. It will pass null through the rest of the expression if Value is null, which will then trigger the Null Coalescing Operator (??) properly.
The C# 5 solution would be to push the coalescing up a bit, as in haim770's answer.
deliveryEvent.CSR_Notes = (rows.Cells["CSR_Notes"].Value ?? "").ToString();
You need to check that the row.Cells["CSR_Notes"] object is not null, but your last code snippet is checking the returned value of the entire expression row.Cells["CSR_Notes"].Value.ToString() and by the time it's evaluated it rightly throws because row.Cells["CSR_Notes"] returns null.
Try this instead:
deliveryEvent.CSR_Notes = (row.Cells["CSR_Notes"].Value ?? "").ToString();
See MSDN
You are calling .ToString() on an object that is null. That's why you receive the error. Here's a simpler reproduction:
MyObject obj = null;
string result = obj.ToString();
You can avoid this by using the null conditional operator (sometimes known as "elvis operator")
deliveryEvent.CSR_Notes = row.Cells["CSR_Notes"].Value?.ToString() ?? "";
This will only call .ToString() on Value if Value is not null.

Is there a less verbose and kludgy way to make otherwise-null SQL parameters safe?

I've got code for inserting a record into a SQL Server table which in some cases has some null values (if not replaced with pseudo-null (empty) vals first). Specifically, they are varchars.
If I don't check for null and assign string.empty in those instances:
if (null == _PatternOrdinal)
{
rs.PatternOrdinal = string.Empty;
}
else
{
rs.PatternOrdinal = _PatternOrdinal;
}
...it throws the exception, "The parameterized query '(#Unit varchar(25),#ReportID int,#NextExecution datetime,#NextEx' expects the parameter '#PatternOrdinal', which was not supplied."
IOW, if the code is simply this:
rs.PatternOrdinal = _PatternOrdinal;
...instead of the if block above, it crashes.
So I have to do that with several parameters. Is there a less verbose way to circumvent this periodic derailing?
You can use null-coalescing operator:
rs.PatternOrdinal = _PatternOrdinal ?? string.Empty;
It returns the left-hand operand if the operand is not null; otherwise it returns the right hand operand.
But be aware that an empty string and a null value are not the same. An empty string is still a value, but a null means that there is no defined value.
In those cases where you need to save null values you should use DbNull.Value instead of an empty string.

Setting DateTime property to null

So I have this property and would like to either set the value to what is coming back from the db or to null if it is empty. It is possible to do this with an if-else, but for cleaner code, I would like to use the ternary operator. Could someone point out the mistake I am making. Thanks!!!
public DateTime? OptionExpiration {get;set;}
//actually sets the value to null
if(String.IsNullOrEmpty(dr["OPTION_EXPIRATION"].ToString())){
OptionExpiration = null;
}else{
OptionExpiration = DateTime.Parse(dr["OPTION_EXPIRATION"].ToString());
}
//so I check the to see if the string is empty or null, then try to set the value but recieve this error: Error 2 Operator '|' cannot be applied to operands of type '' and 'System.DateTime?'
String.IsNullOrEmpty(dr["OPTION_EXPIRATION"].ToString())
? OptionExpiration = null
| OptionExpiration = DateTime.Parse(dr["OPTION_EXPIRATION"].ToString())
;
You are using the ternary operator wrong.
It should be:
OptionExpiration = String.IsNullOrEmpty(Convert.ToString(dr["OPTION_EXPIRATION"]))
? (DateTime?)null
: DateTime.Parse(dr["OPTION_EXPIRATION"].ToString())
;
So:
assignment = condition ? trueExpression : falseExpression;
If the field is a date in your database, it might be better to do this:
OptionExpiration = Convert.IsDBNull(dr["OPTION_EXPIRATION"])
? (DateTime?)null
: (DateTime)dr["OPTION_EXPIRATION"]
;
I would use an extension method like this:
public static Nullable<DateTime> AsNullableDateTime(this object item, Nullable<DateTime> defaultDateTime = null)
{
if (item == null || string.IsNullOrEmpty(item.ToString()))
return defaultDateTime;
DateTime result;
if (!DateTime.TryParse(item.ToString(), out result))
return defaultDateTime;
return result;
}
You can pass anything in to this and it will attempt to give you back a date. If it fails for whatever reason (this also checks to make sure the object you send through is not null) you will get a null back; which is fine because you're mapping to a nullable datetime.
To use this you would do something like:
OptionExpiration = dr["OPTION_EXPIRATION"].AsNullableDateTime();
No mess, easy to understand what is happening, abstracting away the clutter, and highly reusable on other parts of your solution.

best way to prevent Null failure with string casting

_callReportCode = reader["Call Report Code"].ToString();
I am attempting to handle the possibility for the object I am calling ToString on to be NULL.
I am going to be using the above statement with several variables and I dont want to make an individual try/catch for each one... what is the best way to do null checking for strings.
Other datatypes ive been doing this:
int.TryParse(reader["Account Number"].ToString(), out _accountNumber);
In this code "reader" refers to a SqlDataReader but thats not really important for this question.
Use the null-coalescing operator: ??
callReportCode = (reader["Call Report Code"] ?? "").ToString();
If the data in your field is DBNull.Value (rather than null), this will still work, because DBNull.Value is not null, so the ?? won't be used, and DBNull.Value.ToString() is "", which is what you'd want.
Convert.ToString(reader["Call Report Code"]);
It will return string.Empty if the value is null.
Source: http://msdn.microsoft.com/en-us/library/astxcyeh.aspx
Update: it also works with DBNull, I've just verified.
Update 2: I decided to bring a more complete test here, just to be sure:
DBNull dbNull = null;
DBNull dbNullEmpty = DBNull.Value;
string stringNull = null;
string stringEmpty = string.Empty;
var outcome1 = Convert.ToString(dbNull);//Empty string
var outcome2 = Convert.ToString(dbNullEmpty);//Empty string
var outcome3 = Convert.ToString(stringNull);//NULL
var outcome4 = Convert.ToString(stringEmpty);//Empty string
If your string is nullable, you need to check the value returned from the SqlDataReader against DBNull.Value:
_callReportCode = reader["Call Report Code"] as string;
If the object returned by reader["Call Report Code"] is not a string, it's DBNull.Value, so the as cast is going to set the value of _callReportCode to null as well.
If you must set the string to a non-null in case the database value is missing, add ??, like this:
_callReportCode = (reader["Call Report Code"] as string) ?? string.Empty;
My suggestion is to never convert ToString when the data isn't a string, and if the data is already a string, then calling ToString is redundant, and a cast is all that's required.
I am making an assumption that the datatype in the database is integer, in which case, you can use a nullable int.
int? accountNumber = reader["Account Number"] == DBNull.Value ? null : (int?)reader["Account Number"];
I have made an extension method to do just this thing.
public static class SqlDataReaderExtensions
{
public static T Field<T>(this SqlDataReader reader, string columnName)
{
object obj = reader[columnName];
if (obj == null)
{
throw new IndexOutOfRangeException(
string.Format(
"reader does not contain column: {0}",
columnName
)
);
}
if (obj is DBNull)
{
obj = null;
}
return (T)obj;
}
}
Usage
int? accountType = reader.Field<int?>("Account Number"); // will return NULL or the account number.
The easiest way I have found is
_callReportCode = reader["Call Report Code"] + "";
i have some easiest and common Method.
public static string ToNULLString(this string Values)
{
if (string.IsNullOrEmpty(Values))
{
return "";
}
else
{
return Values.ToString();
}
}
use in C#
string item = null;
string value = item.ToNULLString();
you could create a method that you call when you want to make the check.
This way you have to type the try catch only once...
or you can create an extension method for string class to do this
_callReportCode = Convert.ToString(reader["Call Report Code"]) should ensure there are no null there.
Use following line of code:
_callReportCode = String.IsNullorEmpty(reader["Call Report Code"]) ?
String.Empty :
reader["Call Report Code"].ToString();
instead of the following line:
_callReportCode = reader["Call Report Code"].ToString();
I like using a combination of the null-coalescing operator and the null conditional operator:
string nn = MyObject.myNullableVar?.ToString() ?? "";
it's basically the same as this
string ss = (MyObject.MyNullableVar == null) ? "" : MyObject.MyNullableVar.ToString();
but shorter.
You can perform a check using String.IsNullOrEmpty() to ensure that it isn't going to be null, or you could write an extension method to perform some action if it's not null and another / nothing if it is.

Categories