Checking if JValue is null - c#

Why this code doesn't run, I want to check if JSON contains integer for key PurchasedValue or not? () :
public PropertyInfo(Newtonsoft.Json.Linq.JToken jToken)
{
this.jToken = jToken;
int PurchasedValue = (int)(jToken["PurchasedValue"].Value ?? 0);
}
the error is :
Error CS0019: Operator `??' cannot be applied to operands of type `method group' and `int' (CS0019)

From my understanding jToken["PurchasedValue"] is a nullable value.
You have to use
int PurchasedValue = (int)(jToken["PurchasedValue"]?? 0);
nullableObj.Value can be only used without error only when there is a value for the nullableObj
Otherwise You can use like
int PurchasedValue = jToken["PurchasedValue"].HasValue?jToken["PurchasedValue"].Value: 0;
This May not even need type casting

You can compare the token type:
var purchasedValueToken = jToken["PurchasedValue"];
int purchasedValue = purchasedValueToken.Type == JTokenType.Null ? 0 : purchasedValueToken.Value<int>();

Well, there are couple of things here :
The jToken["PurchasedValue"] could return anything so a type check would be preferable.
You can change your code as following:
public PropertyInfo(Newtonsoft.Json.Linq.JToken jToken)
{
this.jToken = jToken;
int PurchasedValue = jToken["PurchasedValue"] is int ? jToken["PurchasedValue"] : 0;
}

Related

Explain behaviour terniary operator and default

Can someone please explain the following behaviour?
I am trying to return null, as int?, if a int.TryParse return false.
From the following options, all return null except the second:
var resultInt1 = int.TryParse(null, out var result) ? result : (int?)default; //null
var resultInt2 = int.TryParse(null, out var result2) ? result2 : default; //0
var resultInt3 = int.TryParse(null, out var result3) ? result3 : (int?)null; //null
var resultInt4 = int.TryParse(null, out var result4) ? result4 : default(int?); //null
isn't default for int? null? Why is it returning 0?
The conditional operator always has to select a best type from the types of the two possible results. In 3 of your samples, you're asking it to select between int and int? and it decides that int? is the best type.
However, when you have just int and default, default doesn't have a type and must be inferred from context. So the only possible type the compiler can choose as the type for the conditional is int. Having made that decision, it now knows that default is the same as default(int) which is 0.
If the string to parse is null, Int32.TryParse will always return false, after setting the default value for the out parameter.
So you get always the false part of your expressions but all the out variables above are set to their default value.
Because Int32.TryParse expects the out variable to be an integer, then, if you look at the value set in the out variables you will see that are all set to 0.
You can see this behavior looking at the referencesource site following the source code of Int32.TryParse
In the second case the type is int, not int?.
int.TryParse works with int not int? so it's the else part that dictates int? in the 1st, 3rd and 4th cases.
It becomes clearer if you 'unwind' the code.
//var resultInt1 = int.TryParse(null, out var result) ? result : (int?)default; //null
int result; // <--- int, not 'int?'
int? resultInt1; // has to be nullable
if (int.TryParse(null, out result))
resultInt1 = result;
else
resultInt1 = (int?)default; //null
// var resultInt2 = int.TryParse(null, out var result2) ? result2 : default; //0
// is equivalent (note 'int', not 'int?'
// int resultInt2 = int.TryParse(null, out var result2) ? result2 : default; //0
// is equivalent
int result2; // <--- int, not 'int?'
int resultInt2; // <------------------- here, it's an int
if (int.TryParse(null, out result2))
resultInt2 = result2;
else
resultInt2 = default; <--‐------ the only case with an 'int', not an 'int?'

Assign nullable int to int in ternary operator

I have a class say
class Test
{
int? a;
int b;
}
Now i m creating a object of test class
Test objTest = new Test();
objTest.b = objTest.a;
Here it throws error cannot implicitly convert int? to int.
So i came up with solution
objTest.b = ObjTest.a ?? 0;
Works fine Here But !!!
objTest.b = objTest.a == null ? 0 : objTest.a
Fails ..
Why basically both doing the same checking null value and assign value accordingly
You would still need to cast a to an int in your second example.
objTest.b = objTest.a == null ? 0 : (int)objTest.a
will compile. But just do it the first way you came up with.

Built in CastOrDefault?

I get the feeling there is something built in for this. If object is null i'd like the default value (or specifically 0 and I am only using decimal/int). Is there a built in way to write this function?
static int GetDecimalFromObject(object o){
return o==null?0:(decimal)o;
}
Convert.ToDecimal and Convert.ToInt32 will return zero if passed null.
Try to use Convert.ToDecimal()
A decimal number that is equivalent to value, or 0 (zero) if value is
null.
Try like this;
static decimal GetDecimalFromObject(object o)
{
return o == null ? Convert.ToDecimal(0) : Convert.ToDecimal(o);
}
or more efficient;
static decimal GetDecimalFromObject(object o)
{
return Convert.ToDecimal(o);
}
Firstly, the decimal and int data types can't be null, so they would be 0 by default.
If you have a nullable decimal (decimal?) use the HasValue method to check if it is null then assign your default of 0.
The ?? Operator might help, but you have to provide the default value:
// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;
Just to offer a different solution:
static int GetDecimalFromObject(object o)
{
return o as int? ?? 0;
}
Generic version:
static T GetValueFromObject<T>(object o) where T : struct
{
return o as T? ?? default(T);
}
Note that I've used the as operator. If you prefer to throw an exception in case o is not of the right type, use the cast operator.

How can I compare an integer to the value I get from an enum?

I have the following method and enum:
public int GetRowType(string pk)
{
return Convert.ToInt32(pk.Substring(2, 2));
}
public enum CONTENT {
Menu = 0,
Article = 1,
FavoritesList = 2,
ContentBlock = 3,
Topic = 6,
List = 7
};
Here I am trying to check if the result of my method is equal to the value of the enum but I am getting an error:
GetRowType(content) == CONTENT.Topic
Can someone give me some advice on what I am doing wrong?
Gives me an error: Error 2
Operator '==' cannot be applied to operands of type 'int' and 'Storage.Constants.CONTENT'
Just cast enum value to int, explicitly
GetRowType(content) == (int)CONTENT.Topic
You must explicitly cast your enum to an int:
(int)CONTENT.Topic
Having said that it might make more sense for your method to return an enum (this time explicitly casting your int to the enum within the method)
The whole idea is to work with the enum directly. so to fix up your method and return a enum instead of an integer:
public CONTENT GetRowType(string pk)
{
int temp = Convert.ToInt32(pk.Substring(2, 2));
if (Enum.IsDefined(typeof(CONTENT), temp))
{
return (CONTENT)temp;
}
else throw new IndexOutOfRangeException();
}

Convert null field to zero before converting to int?

In my program, I'm looping through a datatable to get data from each field. One line of my code looks like this:
int LYSMKWh = Convert.ToInt32(resultsDT.Rows[currentRow]["LYSMKWh"]);
Basically, I'm just taking the value that's in the cell and converting it to an int32. I run into a problem, though, when the data in the field is a null. I get an Invalid Cast error message about not being able to convert a "DBNull" to another type.
So, I know that I can just check the value of the field before I try to convert it by doing something like this:
if (resultsDT.Rows[currentRow]["LYSMKWh"] == null)
{
resultsDT.Rows[currentRow]["LYSMKWh"] = 0;
}
But, is there a better way to do this? Is there something I can do "inline" while I'm trying to convert the value without having to resort to using the if ?
EDIT: I did try using this suggested method:
int LYSMKWh = Convert.ToInt32(resultsDT.Rows[currentRow]["LYSMKWh"] ?? "0");
Unfortunately, I still received the Invalid Cast error message with regards to the DBNull type. It was suggested that I could have problems using the ?? operator if the types on either side were different.
Also, since I have complete control over the data that I'm building my datatable with, I changed it so that no null values would be written to any field. So, that pretty much negates the need to convert a null to an int32, in this case. Thanks for all the advice, everyone!
You could do this:
var LYSMKWh =
resultsDT.Rows[currentRow]["LYSMKWh"].Equals(DBNull.Value)
? 0
: Convert.ToInt32(resultsDT.Rows[currentRow]["LYSMKWh"]);
use the ?? operator:
resultsDT.Rows[currentRow][...] ?? "0"
(expecting the field to be a string - if not change the "0")
You may consider using C#'s ?? operator, which checks a value for null and if it's null, assigns a default value to it.
You can use the ?? operator:
object x = null;
int i = (int)(x ?? 0)
You can use a custom convert method:
public static int ConvertToInt32(object value, int defaultValue) {
if (value == null)
return defaultValue;
return Convert.ToInt32(value);
}
You may need overloads that take other types, like string. You may have problems with the ?? operator if the types on either side are different.
You can replace it with a ternary operator:
var rowData = resultsDT.Rows[currentRow]["LYSMKWh"];
int LYSMKWh = rowData != null ? Convert.ToInt32(rowData) : 0;
Alternatively, the ?? operator could work:
int LYSMKWh = Convert.ToInt32(resultsDT.Rows[currentRow]["LYSMKWh"] ?? 0);
But I think that's less readable.
You can use extension Method.
int LYSMKWh = resultsDT.Rows[currentRow]["LYSMKWh"].IfNullThenZero();
Create the below class
public static class Converter
{
public static Int32 IfNullThenZero(this object value)
{
if (value == DBNull.Value)
{
return 0;
}
else
{
return Convert.ToInt32(value);
}
}
}
Check if it's DBNull.Value instead of null:
if (resultsDT.Rows[currentRow]["LYSMKWh"] == DBNull.Value)
{
resultsDT.Rows[currentRow]["LYSMKWh"] = 0;
}
The ternary expression would work like this:
var LYSMKwhField = resultsDT.Rows[currentRow]["LYSMKWh"];
int LYSMKWh = LYSMKwhField != DBNull.Value ? Convert.ToInt32(rowData) : 0;

Categories

Resources