So I know why I have a null reference exception in this case. My question is how I avoid it given this specific use.
I have a function interpreting JSON data like so:
public IActionResult SendLine([FromBody] User data) {
if (_assets.GetPropertyByName(data.Properties.PropertyName) == null) {
_assets.AddProperty(new Property {
IsToggle = data.Properties.IsToggle,
Order = data.Propertis.Order,
Type = data.Properties.Type,
PropertyName = data.Properties.PropertyName
});
}
_assets.AddRow(data);
return Json(data);
}
The problem is that the Property class can have null values like so:
{
properties: {
isToggle: false,
order: 0,
type: null,
propertyName: "Test"
},
....
}
So I get why it throws the exception that "properties" is null since it has a null value. However this is as intended. How do I check to see if the propertyName is null without it throwing that error?
EDIT:
I'm not sure how null conditionals would help this case. If I put it here
if (_assets.GetPropertyByName(data.Properties?.PropertyName) == null)
it will evaluate to null improperly.
Edit: Updated my answer after realizing this is probably closer to what you need (?):
If the if-clause is where your exception is thrown, just split it up a little more:
var propName = data?.Properties?.PropertyName;
var isPropNameFound = !string.IsNullOrEmpty(propName);
var prop = isPropNameFound ? _assets.GetPropertyByName(propName) : null;
if (isPropNameFound && (prop == null))
{
// Add new property if name was given, and it
// was not found to already have been added?
}
That should ensure propName is null if either data.Properties or data.Properties.PropertyName is null, and do so without throwing a NullReferenceException.
After that, it will run the logic in the if block only if propName had a value, and if _assets.GetPropertyByName(propName) did not return anything.
Related
I am trying to use TryGetValue on a Dictionary as usual, like this code below:
Response.Context.Skills[MAIN_SKILL].UserDefined.TryGetValue("action", out var actionObj)
My problem is the dictionary itself might be null. I could simply use a "?." before UserDefined but then I receive the error:
"cannot implicitly convert type 'bool?' to 'bool'"
What is the best way I can handle this situation? Do I have to check if UserDefined is null before using TryGetValue? Because if I had to use Response.Context.Skills[MAIN_SKILL].UserDefined twice my code could look a little messy:
if (watsonResponse.Context.Skills[MAIN_SKILL].UserDefined != null &&
watsonResponse.Context.Skills[MAIN_SKILL].UserDefined.TryGetValue("action", out var actionObj))
{
var actionName = (string)actionObj;
}
Add a null check (?? operator) after the bool? expression:
var dictionary = watsonResponse.Context.Skills[MAIN_SKILL].UserDefined;
if (dictionary?.TryGetValue("action", out var actionObj)??false)
{
var actionName = (string)actionObj;
}
Another option is to compare to true.
It looks slightly weird, but it works with three-valued logic and says: is this value true but not false or null
if (watsonResponse.Context.Skills[MAIN_SKILL]
.UserDefined?.TryGetValue("action", out var actionObj) == true)
{
var actionName = (string)actionObj;
}
You can do the opposite logic with != true: is this value not true, so either false or null
if (watsonResponse.Context.Skills[MAIN_SKILL]
.UserDefined?.TryGetValue("action", out var actionObj) != true)
{
var actionName = (string)actionObj;
}
I'm just looping and appending my properties to a big string:
output.Append(property.GetValue(this).ToString()));
When app breaks in that moment property represent a ProductNumber which is a string, value of this is Product object which has value of ProductNumber = null, so I've tried something like this:
output.Append(property.GetValue(this)?.ToString()));
But anyway it breaks..
How could I improve this code to avoid breaking there?
Thanks
Cheers
It seems that output.Append complains on null values. There are 2 possible sources of pesky nulls here:
property.GetValue(this) returns null and thus ?. in ?.ToString() propagates null
ToString() itself returns null (hardly a case, but still possible)
We can solve both possibilities with ?? operator: let's return an empty string whatever the source of null is:
property.GetValue(this)?.ToString() ?? ""
Final code is
output.Append(property.GetValue(this)?.ToString() ?? "");
This code:
output.Append(property.GetValue(this)?.ToString()));
Is the same as:
object propValue = property.GetValue(this);
string propString = null;
if (propValue != null)
{
propString = propValue.ToString();
}
output.Append(propString); // propString can be null
This can be simplyfied like so:
string propString = property.GetValue(this)?.ToString(); // This performs a ToString if property.GetValue() is not null, otherwise propString will be null as well
output.Append(propValue); // propValue can be null
If you want to prevent calling Append with a null value you can do:
string propString = property.GetValue(this)?.ToString(); // This performs a ToString if property.GetValue() is not null, otherwise propString will be null as well
if (propString == null)
{
propString = string.Empty;
}
output.Append(propValue); // propString is not null
This can be simplified with the null-coalescing operator:
string propString = property.GetValue(this)?.ToString() ?? string.Empty
output.Append(propValue); // propString is not null
I have the following line of code, which is giving me trouble of NPE
ServeUrl = ((NameValueCollection)ConfigurationManager.GetSection("Servers")).Get(ment);
When I write this in the following way, I no longer get the NPE
if (ConfigurationManager.GetSection("Servers") != null && ((NameValueCollection)ConfigurationManager.GetSection("Servers")).Get(ment) != null)
{
ServeUrl = ((NameValueCollection)ConfigurationManager.GetSection("Servers")).Get(ment);
}
Somwhow, the above thing does not look good to my eyes. How can I write this in a better way?
I'd extract a temporary variable:
var section = (NameValueCollection)ConfigurationManager.GetSection("Servers");
if (section != null && section.Get(ment) != null)
{
...
}
Or even:
var section = (NameValueCollection)ConfigurationManager.GetSection("Servers");
if (section != null)
{
var url = section.Get(ment);
if (url != null)
{
ServeUrl = url;
}
}
What would you want to do if GetSection returned null though? Can you actually keep going?
!= means not equal to and == means equal to
If you can't use NULL you can use ""
Apply the condition with logic and then even after it is not getting what you want then:
condition will be false and you also used AND logical operator
I would have used this(FYI,i haven't tried this in compiler):
if (ConfigurationManager.GetSection("Servers")?.Get(ment) is NameValueCollection nvc)
{
ServeUrl = nvc;
}
I am facing inconsistent null value reference errors while I am trying to store my values from a serialized class object.
if ( item.current_location.city!=null )
{
var city = item.current_location.city.Select(i => i.ToString());
}
In the above code snippet, successful insertion takes place even if any index in item array has null values. But it throws exception in some cases,which I don't think can be distinguished in any manner from other cases( when the value is null)
item could be null as well
current_location could be null as well,
not only city.
This would help
if (item != null &&
item.current_location != null &&
item.current_location.city != null) {
...
}
EDIT:
Note: This code works, since c# implements a so-called shortcut-evaluation of Boolean expressions. If item should be null, the rest of the expression would not be evaluated. If item.current_location should be null, the last term would not be evaluated.
(I do not see any insertion in the code above.)
Starting with C#6.0 you can use the null propagation operator (?):
var city = item?.current_location?.city?.Select(i => i.ToString());
if (city != null) {
// use city ...
}
I can't give a definitive answer without seeing your dataset, but you're not checking for null values on the item object or the current_location object. I would suggest you start by changing your test to this:
if (null != item && null != item.current_location && null != item.current_location.city)
{
...
}
How do I determine if an object reference is null in C# w/o throwing an exception if it is null?
i.e. If I have a class reference being passed in and I don't know if it is null or not.
testing against null will never* throw an exception
void DoSomething( MyClass value )
{
if( value != null )
{
value.Method();
}
}
* never as in should never. As #Ilya Ryzhenkov points out, an incorrect implementation of the != operator for MyClass could throw an exception. Fortunately Greg Beech has a good blog post on implementing object equality in .NET.
What Robert said, but for that particular case I like to express it with a guard clause like this, rather than nest the whole method body in an if block:
void DoSomething( MyClass value )
{
if ( value == null ) return;
// I might throw an ArgumentNullException here, instead
value.Method();
}
Note, that having operator != defined on MyClass would probably lead do different result of a check and NullReferenceException later on. To be absolutely sure, use object.ReferenceEquals(value, null)
if(p != null)
{
DoWork(p);
}
Also, the 'as' keyword is helpful if you want to detect if a class is of the right type and use it all at once.
IExample e = p as IExample;
if(e != null)
DoWork(e);
In the above example if you were to cast e like (IExample)e it will throw an exception if e does not implement IExapmle. If you use 'as' and e doesn't implement IExample e will simply be null.
If you look in the majority of the .NET framework source code you will see they put checks like this at the top of their functions.
public void DoSomething(Object myParam)
{
if (myParam == null) throw new ArgumentNullException("myParam");
// Carry on
}
With C# 6.0 this is much more elegant; you can do it in one line :-)
value?.Method();
If "value" is null, nothing will happen - and no exception.
It's nit picky, but I always code these like ...
if (null == obj) {
obj = new Obj();
}
instead of
if (obj == null) {
obj = new Obj();
}
to avoid accidently writing
if (obj = null) {
obj = new Obj();
}
because
if (null = obj) {
obj = new Obj();
}
will give you a compiler error
Or if you are using value types you can read about nullable types: http://www.c-sharpcorner.com/UploadFile/mosessaur/nullabletypes08222006164135PM/nullabletypes.aspx
(YourObject != Null)
you can compare to null?
If it's null instead of throwing an exception you can initialize your object. You can use the Null Pattern.
I have in the application's xaml.cs application derivative definition:
private SortedList myList;
And I want to be able to re-use my constructors. So I needed:
if ( myList == null)
myList = new SortedList();
Thanks Robert!