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<object, Decimal?> convertOrNullDecimal = x => x == null ? (Decimal?)null : Convert.ToDecimal(x);
Func<object, int?> 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
-
3\$\begingroup\$ okay... what's your question? I don't understand where you're going... This reads more like a "I have problem x and I want it solved." and not like "I have solved problem x, is this solution good?" \$\endgroup\$Vogel612– Vogel6122014年10月28日 16:57:14 +00:00Commented Oct 28, 2014 at 16:57
-
1\$\begingroup\$ @Vogel612 it is solved - it works. My question is is there a better way to solve it than making a function (like mine above) for each input type? \$\endgroup\$Dan– Dan2014年10月28日 16:58:12 +00:00Commented Oct 28, 2014 at 16:58
3 Answers 3
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.
Use generics that's all:
public static T? ConvertTo<T>(object x) where T : struct
{
return x == null ? null : (T?)Convert.ChangeType(x, typeof(T));
}
I am not sure why you are worried about doubles coming through instead of Decimals but you could just assign with a ternary like this
var B = A1 == null ? null : A1;
This way B
will be the same type as A1
Most of the time a Method or Function that takes a Decimal value should also take a Double value, Doubles are smaller than Decimals
Single, Double, Decimal are kind of like Integer types
- Single = 4 bytes (short = 2 bytes)
- Double = 8 Bytes (int = 4 bytes)
- Decimal = 12 bytes (long = 8 bytes)
Note: Assuming that decimal values are necessary
You could just do the conversion after you assign to the variable (after checking for null).
You might be able to assign straight across actually
decimal B = A1 == null ? null : A1;
but you need a nullable decimal (decimal?
) Another Assumption
Instead of assigning null to the Decimal you have to assign it's default value using default(decimal?)
which I assume comes out as null.
decimal? B = A1 == null ? default(decimal?) : Convert.ToDecimal(A1);
Google and MSDN are awesome resources to figure stuff like this out.
(as well as StackOverflow answers)
playing around with this if you don't want a nullable Decimal you can also write it like this
decimal C = A1 == null ? default(decimal) : Convert.ToDecimal(A1);
-
1\$\begingroup\$ Yes,
default(decimal?)
is the same asnull
. And instead ofdefault(decimal)
, you can write just0m
. \$\endgroup\$svick– svick2014年10月29日 12:53:02 +00:00Commented Oct 29, 2014 at 12:53