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;
}
Related
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
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.
I'm not talking about javascript, but in javascript, I can declare a string like this:
var identity = {
getUserId: function () {
return 'userid';
}
};
var userid = identity.getUserId() || '';
That means: if identity.getUserId() is null or undefined, the value '' will be casted to userid automatically.
Now, in C#:
public static void AddOnlineUser(this IIdentity identity)
{
string userid = identity.GetUserId();
// long way to check userid is null or not:
if (string.IsNullOrEmpty(userid))
{
userid = "";
}
// invalid C# syntax:
// Operator || cannot be applied to operands of type 'string' and 'string'
// string userid = idenity.GetUserId() || "";
// Only assignment, call, increment, decrement, and new object expressions can be used as a statement
// string.IsNullOrEmpty(userid) ? "" : userid;
}
I don't mean: want to create a C# variable same as javascript syntax. But in this case, is there a way to cast value "" to userid if it's null or empty in 1 line?
The Null Coalescing Operator ??
C# has it's own null-coalescing operator ?? to do this to handle null values :
// This will use the available GetUserId() value if available, otherwise the empty string
var userid = identity.GetUserId() ?? "";
Keep in mind this operator will only work as expected if the first value in your statement is null, otherwise it will use that value. If there is a chance that this isn't the case (and you might encounter a non-null invalid value), then you should consider using a ternary operator instead.
The Ternary Operator ?:
Otherwise, you could use a ternary operator ?: (i.e. an inline if-statement) to perform this check as well. This is similar to the example you provided, however it's worth noting that you need to actually set userid to the result :
// This will set it to empty string if null or empty, otherwise it will use the returned id
userid = String.IsNullOrEmpty(userid) ? "" : userid;
How can I check if any key from json object have null value
JsonObject itemObject = itemValue.GetObject();
string id = itemObject["id"].GetString() == null ? "" : itemObject["id"].GetString();
this is my code but app crashes on it if null value for key "id"
IJsonValue idValue = itemObject.GetNamedValue("id");
if ( idValue.ValueType == JsonValueType.Null)
{
// is Null
}
else if (idValue.ValueType == JsonValueType.String)
{
string id = idValue.GetString();
}
If you do this too much, consider adding extension methods.
To do the opposite use:
IJsonValue value = JsonValue.CreateNullValue();
Read here more about null values.
http://msdn.microsoft.com/en-us/library/ms173224.aspx
The ?? operator is called the null-coalescing operator. It returns the left-hand operand if the operand is not null; otherwise it returns the right hand operand.
if itemObject["id"] is null then the method null.GetString() doesn't exist and you'll get the error specified (null object never has any methods/fields/properties).
string id = itemObject["id"] == null ? (string)null : itemObject["id"].GetString(); // (string)null is an alternative to "", both are valid null representations for a string, but you should use whichever is your preference consistently to avoid errors further down the line
the above avoids calling .GetString() until you've asserted that the ID isn't null (check here for more in-depth), if you're using C#6 you should be able to use the new shorthand:
string id = itemObject["id"]?.GetString();
Here is solution for the issue
string id = itemObject["id"].ValueType == JsonValueType.Null ? "" : itemObject["id"].GetString();
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;
}