HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Cast an object to Decimal? or Int? etc but leave it as null if it is null

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
nullbutdecimalleavecastobjectintetc

Problem

In a case like this:

object A1 = null;
Decimal? B = Convert.ToDecimal(A1);
object A2 = null;
int? C = Convert.ToInt32(A2);


Note that in case where A1 or A2 have values, they appear to be of type double.

B and C will be 0 instead of null. A1 actually comes from Excel via the interop and (Decimal?)A1 throws an error: Specified cast is not valid. yet Convert.ToDecimal(A1) works. The problem is that if A1 is null, I want B to also be null

So at the moment I'm solving it like this:

Func convertOrNullDecimal = x => x == null ? (Decimal?)null : Convert.ToDecimal(x);
Func convertOrNullInt32 = x => x == null ? (int?)null : Convert.ToInt32(x);

B = convertOrNullDecimal(A1);
C = convertOrNullDecimal(A2);


Is this a reasonable way to go? Or can I refactor that into a single function? It's possible I'll have to add other numeric data types later on...

I tried it like this:

public static Decimal? convertOrNull(object x)
{
    return x == null ? (Decimal?)null : Convert.ToDecimal(x);
}
public static int? convertOrNull(object x)
{
    return x == null ? (int?)null : Convert.ToInt32(x);
}


but then the calls become ambiguous. I guess you can't overload based on output variable type...

Also note that if I try B = A1 as Decimal?, then if A1 had a numerical value, B is still null because it looks like Excel passed numeric cells as doubles and empty cells as null

Solution

If you know that the object is always either double or null, then that's exactly what the double? type can represent and you can convert to that using a cast:

object obj = ...;
double? doubleValue = (double?)obj;


And once you have double?, you can cast it to decimal? and it will work both for the case when the value is null and when isn't:

decimal? decimalValue = (decimal?)doubleValue;


Or, on a single line:

decimal? decimalValue = (decimal?)(double?)obj;


Apart from being clear, this approach is also likely going to be pretty efficient.

Code Snippets

object obj = ...;
double? doubleValue = (double?)obj;
decimal? decimalValue = (decimal?)doubleValue;
decimal? decimalValue = (decimal?)(double?)obj;

Context

StackExchange Code Review Q#68206, answer score: 13

Revisions (0)

No revisions yet.