有一种将对象转换为十进制的单行方式吗?

时间:2013-01-02 17:32:53

标签: c# casting decimal

是否有单行方式将对象转换为decimal?数据类型?

我的代码看起来像这样:

foreach(DataRow row in dt.Rows)
{
    var a = new ClassA()
    {
         PropertyA = row["ValueA"] as decimal?,   
         PropertyB = row["ValueB"] as decimal?,
         PropertyC = row["ValueC"] as decimal?
    };

    // Do something

}

然而,将对象强制转换为decimal?并不像我期望的那样工作,并且每次都返回null。

从Excel文件中读取数据行,因此如果有值,则每行中对象的数据类型为double,如果为空,则为string

执行此转换的suggested method是使用decimal.TryParse,但是我不想为类中的每个小数属性创建一个临时变量(我的实际类中有大约7个属性,是小数,而不是3)。

decimal tmpvalue;
decimal? result = decimal.TryParse((string)value, out tmpvalue) ?
                  tmpvalue : (decimal?)null;

有没有办法可以在单行中向decimal?投射潜在的空值?

我尝试了here发布的答案,但它似乎无法正常工作,并且还为null提供row["ValueA"] as string值,因为null会返回{{1}}。

7 个答案:

答案 0 :(得分:6)

您最好的选择是创建一个扩展方法。这是我使用的,虽然您可以调整它以返回decimal?

public static class ObjectExtensions
{
    public static decimal ToDecimal(this object number)
    {
        decimal value;
        if (number == null) return 0;
        if (decimal.TryParse(number.ToString().Replace("$", "").Replace(",", ""), out value))
            return value;
        else
            return 0;
    }
    public static decimal? ToNullableDecimal(this object number)
    {
        decimal value;
        if (number == null) return null;
        if (decimal.TryParse(number.ToString().Replace("$", "").Replace(",", ""), out value))
            return value;
        else
            return null;
    }

}

然后,您可以在任何对象上调用.ToDecimal()来使用它,就像调用.ToString()一样。

它不是一行,但它只是在使用它时的单个函数调用,并且它是非常可重用的。

编辑添加可空版本

答案 1 :(得分:4)

  

提供一个值,它读取为double,否则我认为它是一个字符串

好的,所以这会使问题变得复杂,因为有时你需要解析它,有时你却不需要解析它。

我们要做的第一件事就是检查它是否已经是double并投射它,因为施法比解析要便宜得多;解析很昂贵。

鉴于这个逻辑非常重要,它属于它自己的方法:

public static deciaml? getDecimal(object rawValue)
{
    decimal finalValue;

    double? doubleValue = rawValue as double?;
    if(doubleValue.HasValue)
        return (decimal) doubleValue.Value;
    else if(decimal.TryParse(rawValue as string, out finalValue))
    {
        return finalValue;
    }
    else
    {
        return null;//could also throw an exception if you wanted.
    }
}

如果你知道它总是双倍的,你永远不会想要字符串值,那么它仍然更容易。在这种情况下,您需要将其转换为double,首先,因为它是真实类型,然后您可以轻松地将其转换为小数:

PropertyA = (decimal?)(row["ValueA"] as double?);

答案 2 :(得分:1)

decimal.TryParse是要走的路。只需创建一个辅助方法并返回值。几乎和你提到的代码相同:

private decimal? convertToNullableDecimal(object value){
  decimal tmpvalue;
  return decimal.TryParse((string)value, out tmpvalue) ? tmpvalue : (decimal?)null;
}

<强>更新

这假设你需要一个可以为空的十进制数。否则,按照其他答案中的建议,使用内置方法:Convert.ToDecimal

答案 3 :(得分:0)

尝试类似

的内容
Func<object, decimal?> l_convert =
    (o) => decimal.TryParse((o ?? "").ToString(), out tmpvalue) ? tmpvalue : (decimal?)null;

var a = new ClassA()
{
     PropertyA = l_convert(row["ValueA"]),   
     PropertyB = l_convert(row["ValueB"]),
     PropertyC = l_convert(row["ValueC"])
};

答案 4 :(得分:0)

希望这有帮助

decimal temp;
foreach(DataRow row in dt.Rows)
{
    var a = new ClassA()
    {
         PropertyA = Decimal.TryParse(row["ValueA"].ToString(), out temp) ? Convert.ToDecimal(row["ValueA"].ToString()) : (Decimal?) null,   
         ....
    };

    // Do something

}

答案 5 :(得分:0)

您可以尝试Decimal.Parse方法。

public static decimal ToDecimal(this string value){

    try
    {
        return Decimal.Parse(value);
    }   
    catch (Exception)
    {
        //  catch FormatException, NullException
        return 0;
    }
}

//  use
PropertyA = row["ValueA"].ToString().ToDecimal();
PropertyB = row["ValueB"].ToString().ToDecimal();
PropertyC = row["ValueC"].ToString().ToDecimal();

答案 6 :(得分:0)

Convert.ToDecimal(object)几乎可以做你想要的。它将正确转换double值(不首先转换为字符串),还可以处理可转换为decimal的其他类型。它做得不好的一件事是空转换(或将String.Empty转换为null)。我会试着用扩展方法处理。

public static class ObjectToDecimal
{
  public static decimal? ToNullableDecimal(this object obj)
  {
    if(obj == null) return null;
    if(obj is string && String.Empty.Equals(obj)) return null;
    return Convert.ToDecimal(obj);
  }
}

请记住,Convert.ToDecimal(object)可以抛出异常,因此您必须注意这一点。