遇到Nullable <t> </t>的问题

时间:2014-06-24 00:28:54

标签: c# xml linq nullable

我正在使用LINQ和XDocument来解析XML文件。 XML中的某些字段不是固定的,因为它们有时可能是双字符串或字符串。通常它会是一个双精度数字,但是一个字符串表示数据不可用。

例如:

<current_observation>
    <temp_c>12.1</temp_c>
    <temp_c>NA</temp_c>
</current_observation>

我读取XML字段,然后在新对象实例中设置属性。像这样:

        var data = from i in weatherResponse.Descendants("current_observation")
                   select new CurrentConditions
                   {
                       // Attempt to parse. Set to null if not a double.
                       // This is one of the areas I'm having trouble with.
                       TemperatureC = Utilities.ParseDoubleValue(i.Element("temp_c"))

                       // If I use the following line instead then it works without problem.
                       // But this misses out all of the safe parsing.
                       // TemperatureC = (double)i.Element("temp_c")
                   };

我决定使用Nullable类型,以便我可以使用TryParse将字段解析为double,或者如果不可能则将属性设置为null。

以下是我用来尝试解析字段的代码:

    public static class Utilities
    {
        public static double? ParseDoubleValue(object inputValue)
        {
            if (inputValue == null)
                return null;

            double returnValue;

            return double.TryParse(inputValue.ToString(), out returnValue) ? returnValue : (double?)null;
        }
}

但是,似乎在我的代码中某处并没有正确地解析字段,因为如果我这样做:

    if(currentConditions.TemperatureC.HasValue)
        Console.WriteLine("Has a value: {0}", currentConditions.TemperatureC.Value);
    else
        Console.WriteLine("Not Avaliable.");

然后HasValue将始终返回 false

我的问题:为什么我尝试解析值的方法不起作用?我是否误解了TryParse和可空类型的用法?

2 个答案:

答案 0 :(得分:2)

i.Element返回一个XElement,而不是值。而且,当然,这对于一个数字来说是不可解析的。您需要i.Element("temp_c").Value

答案 1 :(得分:2)

XElement为各种数字类型定义explicit type conversions。因此,(double)i.Element("temp_c")被允许并将XElement的{​​{3}}转换为双数据类型(通过内部调用Double.Parse)。

XElement作为object类型的参数传递到您的Utilities.ParseDoubleValue方法时,您将传递整个XElement。对inputValue.ToString()的调用不返回12.1,而是返回<temp_c>12.1</temp_c>value。当然,double.TryParse("<temp_c>12.1</temp_c>")会失败。

错误在于您最有可能希望为此方法提供XElement的字符串值,而不是XElement本身。这是一个简单的改变问题:

TemperatureC = Utilities.ParseDoubleValue(i.Element("temp_c"))

TemperatureC = Utilities.ParseDoubleValue(i.Element("temp_c").Value)

其次,作为防御措施,您可能需要重新考虑方法的方法签名:

public static double? ParseDoubleValue(object inputValue)

这将接受任何对象,但您最终有兴趣转换调用者提供的字符串。将其更改为仅接受字符串将确保调用者提供字符串,否则将导致编译错误。

public static double? ParseDoubleValue(string inputValue)