patterncsharpMinor
Computing value sums in a custom grid
Viewed 0 times
gridvaluecustomsumscomputing
Problem
I have written a helper method which computes the sum of values in some custom grid, given the column indexes. The method appears to work (for a decimal - as Anthony pointed out, I need to test this further), but I am not at ease with the following conversions:
They seem too indirect, but
decimal valIfNull = (decimal)(object)valueIfNull;
return (T)(object)sum;They seem too indirect, but
Convert.ChangeType also returns an object type, so another cast is needed anyway. Also, I believe that Convert.ChangeType can convert a string such as "123.456" into a proper decimal value, but this is not the behavior I want in this case. I would like to see an invalid cast exception in that case. So, is what I have good enough, or is there a better way?private T SumColumns(T valueIfNull, params short[] columnIndexes)
where T : struct, IConvertible
{
// Since we do not know what exactly T is, we will compute things as if it was a decimal.
// If this works reasonably well, then this trick should be used elsewhere.
// I am not sure if this is the best way to go about casting
decimal valIfNull = (decimal)(object)valueIfNull;
// Here this.GetCurrentRowValue is another generic function I wrote ...
decimal sum = columnIndexes.Select(columnIndex => this.GetCurrentRowValue(columnIndex: columnIndex, valueIfNull: valIfNull)).Sum();
return (T)(object)sum;
}Solution
You've already placed a constraint on the first parameter that it should be
Converting back to the generic type won't be as straight forward. When casting between an
Your best (and probably only) option would be to convert it to a
If you know for sure that the types that are used here can be converted from a
IConvertible, so the methods of that interface is available to you.decimal decimalValueIfNull = valueIfNull.ToDecimal(CultureInfo.InvariantCulture);Converting back to the generic type won't be as straight forward. When casting between an
object and a value type, no conversions will be made and you are just boxing/unboxing the value. Since you have a constraint that the type be a value type, the casts won't really work here. In fact, I don't think it's even possible to do so generically. If a conversion exists from decimal to the type you wouldn't be able to express that here. And you won't be able to use the Convert class to do the conversion, there's no way to "add" conversions to existing convertible types.Your best (and probably only) option would be to convert it to a
dynamic variable and let the runtime figure out whether or not that conversion exists. That way if you have a custom ValueType here that has an implicit or explicit conversion from a decimal, it will be used.return (T)(dynamic)sum;If you know for sure that the types that are used here can be converted from a
decimal, then you could convert back using IConvertible.ToType().return ((IConvertible)sum).ToType(typeof(T), CultureInfo.InvariantCulture);Code Snippets
decimal decimalValueIfNull = valueIfNull.ToDecimal(CultureInfo.InvariantCulture);return (T)(dynamic)sum;return ((IConvertible)sum).ToType(typeof(T), CultureInfo.InvariantCulture);Context
StackExchange Code Review Q#11156, answer score: 4
Revisions (0)
No revisions yet.