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

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.

Related

Check if child object value exists NullReferenceException

I'm pretty new to C#. While attempting to set a local variable value, I'm running into a NullReferenceException.
It appears that the Buyer object is null, which I'm assuming is why it can't figure out the Buyer.Username value. What I'm not sure about is how to check if Buyer is not null AND that the Buyer.Username has a non-null value (in the most simple way possible). Unfortunately, I'm using C# 7.3 which doesn't appear to have support for the ?? operator.
BuyerUserName = string.IsNullOrEmpty(model.Transactions[i].Buyer.Username) ? "" : model.Transactions[i].Buyer.Username
Both ?? and ?. were introduced in C# 6, so you can use them:
BuyerUserName = model.Transactions[i].Buyer?.Username ?? string.Empty;
But even without that, there is nothing wrong with taking more than one line to do something, and you could just use an if statement:
var buyer = model.Transactions[i].Buyer;
if (buyer != null && buyer.Username != null)
BuyerUserName = buyer.Username;
else
BuyerUserName = string.Empty;

How to make the variable empty if the Jobject is empty in C#

I am getting a Null reference exception when the Jobject is empty.
var subjects = item.SelectToken("$.subjects").ToObject<List<JObject>>()
I am want to set var subjects as empty when Jobject empty without throwing an error.
THanks
var subjects = item.SelectToken("$.subjects")?.ToObject<List<JObject>>() ?? new List<JObject>();
List<...>
List is a collection and you need to define what's in the List. Like List<string>, List<object>, or, for your code, List<JObject>.
SelectToken("$.subjects")?.
This means that if SelectToken returns null, it stops there without doing .ToObject, and returns null.
The issue here is that SelectToken will return null when it can't find any object, and when you do .ToObject on a null you get a NullException. So one'd usually check if an object is null before further using its properties or functions.
The question mark - Null-Conditional Operator (Official documents) is a quick syntactic sugar to achieve that, without having to write conditions like
if (... == null)
{ ...convert to list... }
else
{ ...make empty list...}
?? new List()
Not sure what you mean by empty, if you don't want null, but an empty List, Null-coalescing Operator might come to help.
It means that if the statement before ?? is null, returns the statement after ?? instead.
For example, string a = b ?? c means:
string a = b != null ? b : c
But notice that a still can be null if c is null.
It's also a syntactic sugar to help you avoid writing long statements for these checks are frequently needed.

Can anyone understand/explain this String Extension?

We have a file called "StringExtensions" which works as a "class" which can be used for multiple datasets/models I assume.
Can anyone help understand what this ToSafeString does to a string?
public static string ToSafeString(this object source)
{
return source?.ToString() ?? string.Empty;
}
It checks if the object is not null with source?. If it is not null, then ToString() is called and the result is returned. If it is null, thenstring.Empty returned.
It uses (.?) null conditional and (??) null-coalescing operators.
Firstly source?. checks to see if the object being passed in is null, if it is that entire portion (source?.ToString()) will return null and due to the ?. operator the .ToString() does not get evaluated. This operator is short hand and is equivalent to writing:
if(source != null) {
return source.ToString();
} else {
return null;
}
Next, the null coalescing operator ( ?? ) kicks in and it will return string.Empty instead of just a null if either source or the return from .ToString() was null.
If called with null it will return string.Empty
If called on an object that has a .ToString() method that returns null, it will also return string.Empty
If called with an object that has a value to return from .ToString() it will return that value.

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.

using the ?? operator and dealing with a null value

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() ?? "";

Categories