跨区域十进制/双重解析

Dan*_*dor 5 c# parsing regional-settings

事实上,我有多个系统可以生成数字数据,它们存储在一些Web服务器上的文本文件中.一些系统使用小数点作为分数分隔符,一些系统使用十进制逗号作为相同.

应用程序(胖客户端,.net 2.0)也可以在任何一种系统上运行.

所以在经历了一些磕磕绊绊之后我做到了这一点:(http://pastebin.com/vhLXABDD)

    public static bool HasDecimalComma;
    public static bool HasDecimalPeriod;

    public static double GetNumber(string NumberString)
    {
        if (!HasDecimalComma && !HasDecimalPeriod)
        {
            string s = string.Format("{0:0.0}", 123.123);
            if (s.Contains('.'))
            {
                HasDecimalPeriod = true;
            }
            else if (s.Contains(','))
            {
                HasDecimalComma = true;
            }
            else
            {
                throw new SystemException(string.Format("strange number format '{0}'", s));
            }
        }
        if (HasDecimalComma)
        {
            return double.Parse(NumberString.Replace('.', ','));
        }
        if (HasDecimalPeriod)
        {
            return double.Parse(NumberString.Replace(',', '.'));
        }
        throw new ArgumentException(string.Format("can't parse '{0}'", NumberString));
    }
Run Code Online (Sandbox Code Playgroud)

你会建议更好,更优雅的方式吗?

编辑:

我很抱歉之前没有提及它,因为你的答案倾向于那个方向 - 我不能用数字存储生成文化,我只能尝试'检测'它.

SWe*_*eko 1

如果您无法更改调用站点,并且保证小数分隔符旁边不会出现其他类型的分隔符,那么您或多或少可以使用您的方法。我会建议

\n\n
    \n
  1. \xd0\x9 将HasDecimalComma和覆盖HasDecimalPeriod到方法主体 - 在这种情况下绝对不需要全局状态。
  2. \n
  3. 使用TryParse代替Parse,因为预计这些数字可能有错误。
  4. \n
  5. 明确指定InvariantCulture区域性(有小数点)。
  6. \n
  7. 允许既没有逗号也没有句点的数字,因为“3”毕竟是浮点数。
  8. \n
\n\n

所以沿着这些思路:

\n\n
///comment the method assumptions here\n///otherwise the method might seem wrong\npublic static double GetNumber(string numberString)\n{\n   bool hasDecimalComma = numberString.Contains(\',\');\n   if (hasDecimalComma)\n     numberString = numberString.Replace(\',\', \'.\')\n   double result;\n   bool success = double.TryParse(numberString, \n                      NumberStyles.Float, \n                      CultureInfo.InvariantCulture,\n                      out result);\n   if (success)\n     return result;\n   else \n     throw new ArgumentException(\n                           string.Format("can\'t parse \'{0}\'", numberString));\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

(老答案,原则上好,实践中不可能)

\n\n

我建议沿着字符串存储生成的区域性,然后使用它来调用方法,沿着这些线(使用double.TryParse):

\n\n
public static double GetNumber(string numberString, CultureInfo culture)\n{\n   double result;\n   bool success = double.TryParse(numberString, \n                          NumberStyles.Float | NumberStyles.AllowThousands, \n                          culture,\n                          out result);\n   if (success)\n      return result;\n   else \n      throw new ArgumentException(\n                               string.Format("can\'t parse \'{0}\'", numberString));\n}\n
Run Code Online (Sandbox Code Playgroud)\n