3

I've got an NSDecimalNumber from StoreKit's SKProduct class, and I want to convert it to C#'s decimal type to minimize loss of precision. Is there a straightforward way to do such a thing?

I figure my two choices are:

  1. Assume that I understand the binary implementation of each and do my own bit-wise conversion, or
  2. Have NSDecimalNumber give me a string and then have decimal parse it.

I figure option 1 is way too much work and probably even brittle, so I'm inclined to go with option 2. But that doesn't seem like the best I can do, either. (I can live with how slow it'll be, because it happens exceptionally rarely.

sblom
  • 26,911
  • 4
  • 71
  • 95

3 Answers3

5

NSDecimal and NSDecimalNumber structures representation are not identical to .NET System.Decimal.

Conversion is always possible but not easy. If performance is not a huge matter then you'll best served by using the string representation to convert between them.

poupou
  • 43,413
  • 6
  • 77
  • 174
  • 1
    Problem is that `decimal.Parse()` is not reliable between different cultures. If `NSDecimalNumber` produces the string `4.99` and you use `decimal.Parse` on an iPad set to, say, Sweden, you will get a parse error since it's expecting `4,99` instead of `4.99`. (this is an actual issue for me since `NSDecimalNumber` is *always* returning `4.99` no matter what culture my iPad is set to.) – Kirk Woll Mar 01 '13 at 00:15
  • Not a problem :-) There's an overload for `Decimal.Parse` that accept a `CultureInfo` -> http://msdn.microsoft.com/en-us/library/t7xswkc6.aspx quote: The provider parameter is an IFormatProvider implementation, such as a NumberFormatInfo or CultureInfo object. – poupou Mar 01 '13 at 00:20
  • Now I feel like an idiot for not thinking of that. Thanks for the tip, worked like a champ! – Kirk Woll Mar 01 '13 at 00:23
  • 1
    Maybe Xamarin should add a better method to convert decimals. – Felix K. Apr 08 '13 at 19:02
4

Just because this tripped me up and cost me quite some time here's a couple extension methods I now use for conversion between NSDecimal and decimal. This was quite frustrating and I am surprised there is no better way built in.

public static class NumberHelper
{
    public static decimal ToDecimal(this NSDecimal number)
    {
        var stringRepresentation = new NSDecimalNumber (number).ToString ();
        return decimal.Parse(stringRepresentation, CultureInfo.InvariantCulture);
    }

    public static NSDecimal ToNSDecimal(this decimal number)
    {
        return new NSDecimalNumber(number.ToString(CultureInfo.InvariantCulture)).NSDecimalValue;
    }
}
Softlion
  • 12,281
  • 11
  • 58
  • 88
BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
1

Since Xamarin iOS SDK 12, operators are available for explicitly converting an NSDecimal to a decimal and implicitly converting a decimal to an NSDecimal.

Using these operators, you can take the following code as an example for achieving your goal:

var nsDecimalNumber = new NSDecimalNumber("128.478", new NSLocale("en-US"));
var nsDecimal = nsDecimalNumber.NSDecimalValue;
var csharpDecimal = (decimal)nsDecimal;
var nsDecimalAfterConversion = (NSDecimal)csharpDecimal;
var nsDecimalNumberAfterConversion = new NSDecimalNumber(nsDecimalAfterConversion);
sblom
  • 26,911
  • 4
  • 71
  • 95
Benjamin
  • 830
  • 1
  • 8
  • 16