3

我正在为一个项目构建一个 XML Deserializer,并且我经常遇到这种类型的代码情况:

var myVariable = ParseNDecimal(xml.Element("myElement")) == null ? 
                 0 : ParseNDecimal(xml.Element("myElement")).Value;

有没有更好的方法来写这个声明?

编辑:也许我应该澄清我的例子,因为我确实有一个帮助方法来将字符串解析为小数。

4

3 回答 3

6

您可以使用扩展方法:

public static T TryGetValue<T>( this XmlElement element ) {
    if ( null == element ) return default(T);
    return (T)element.Value;
}
...
...
var myVariable = xml.Element("myElement").TryGetValue<decimal>();

编辑:

“通用”解决方案:

static class Program {
    static void Main() {
        var xmlDecimal = new XElement( "decimal" );
        xmlDecimal.Value = ( 123.456m ).ToString();
        decimal valueOfDecimal_1 = xmlDecimal.ValueAs<decimal>( decimal.TryParse );
        bool valueOfBool_1 = xmlDecimal.ValueAs<bool>( bool.TryParse );

        var xmlBool = new XElement( "bool" );
        xmlBool.Value = true.ToString();
        decimal valueOfDecimal_2 = xmlBool.ValueAs<decimal>( decimal.TryParse );
        bool valueOfBool_2 = xmlBool.ValueAs<bool>( bool.TryParse );
    }
}

public static class StaticClass {
    public delegate bool TryParseDelegate<T>( string text, out T value );
    public static T ValueAs<T>( this XElement element, TryParseDelegate<T> parseDelegate ) {
        return ValueAs<T>( element, parseDelegate, default( T ) );
    }
    public static T ValueAs<T>( this XElement element, TryParseDelegate<T> parseDelegate, T defaultValue ) {
        if ( null == element ) { return defaultValue; }

        T result;
        bool ok = parseDelegate( element.Value, out result );
        if ( ok ) { return result; }

        return defaultValue;
    }
}
于 2009-02-08T22:47:24.273 回答
5

编辑:鉴于已编辑的问题,这要简单得多。

它再次使用扩展方法,但现在无需在方法中进行转换。

var myVariable = ParseNDecimal(xml.Element("myElement").ValueOrDefault("0"));

...

public static string ValueOrDefault(this XElement element, 
                                     string defaultValue)
{
    return element != null ? element.Value : defaultValue;
}

如果你不喜欢使用字符串参数的方法,你可以让它 takeobject和 call ToString,然后像这样调用它:

var myVariable = ParseNDecimal(xml.Element("myElement").ValueOrDefault(0m));

但是,这对我来说感觉有点不对劲。它假定解析将与ToString格式化相反。

原始答案

该语言没有什么特别可以帮助您的。(我不确定你的代码是否正确——你的意思不是XAttribute吗?)我建议编写一个实用程序方法:

var myVariable = xml.Element("myElement").ValueOrDefault(0m);

...

public static decimal ValueOrDefault(this XElement element, 
                                     decimal defaultValue)
{
    return element != null ?(decimal) element.Value : defaultValue;
}

如果你调整问题中的代码,我也会对这里的代码做同样的事情。我怀疑您确实是要使用XAttribute,这会导致泛型出现问题-我没有以通用的方式编写上述内容,因为我相信您会想要调用XAttribute“转换为十进制”运算符。通用转换不会这样做,因为它在编译时不知道您想要什么样的转换。但是,您可以为您感兴趣的所有结果类型重载上述方法。

于 2009-02-08T22:47:25.083 回答
1

你可以使用?? 运算符写得更干净一些,但我不确定你应该...

Element()如果没有具有该名称的子元素,则返回 null,因此您可以使用 ?? 滑入默认元素。您需要在调用(decimal)演员表之前执行此操作:

var myVariable 
    = (decimal)(xml.Element("myElement") ?? new XElement("myElement", 0));

就像我说的那样,虽然这会起作用,但我不确定你是否应该这样做。YMMV。

于 2009-02-08T23:01:59.993 回答