C# ?? 与 ? 结合:问题

发布于 2024-07-13 12:35:22 字数 281 浏览 10 评论 0原文

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

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

是否有更好的方法来编写此语句?

编辑:也许我应该澄清我的示例,因为我确实有一个辅助方法将字符串解析为十进制。

I'm building an XML Deserializer for a project and I run across this type of code situation fairly often:

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

Is there a better way to write this statement?

EDIT : Perhaps I should have clarified my example as I do have a helper method to parse the string into a decimal.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

抚你发端 2024-07-20 12:35:23

您可以使用扩展方法:

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;
    }
}

You can use extension method:

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>();

EDIT:

The "universal" solution:

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;
    }
}
柏拉图鍀咏恒 2024-07-20 12:35:23

编辑:考虑到编辑后的问题,这要简单得多。

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

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

...

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

如果您不喜欢采用字符串参数的方法,您可以让它采用 object 并调用 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“转换为十进制”运算符。 通用强制转换不会这样做,因为它不知道编译时需要哪种类型的转换。 但是,您可以为您感兴趣的所有结果类型重载上述方法。

Edit: Given the edited question, this is much simpler.

Again it uses an extension method, but now there's no need to do a conversion in the method.

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

...

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

If you don't like the method taking a string parameter, you could make it take object and call ToString, then call it like this:

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

However, that feels a little bit wrong to me. It assumes that the parsing will be the reverse of ToString formatting.

Original answer

There's nothing particularly in the language to help you. (I'm not sure that you've got the exact code right - don't you mean something with an XAttribute?) I'd suggest writing a utility method:

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

...

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

If you adjust the code in the question, I'll do likewise for the code here. I suspect you did mean to use XAttribute, which leads to a problem with generics - I haven't written the above in a generic way, because I believe you will want to call the XAttribute "conversion to decimal" operator. A generic cast won't do that, as it doesn't know what kind of conversion you want at compile time. You can, however, overload the above method for all the result types you're interested in.

永不分离 2024-07-20 12:35:23

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

Element() 返回 null ,因为没有具有该名称的子元素,所以这就是你可以使用 ? 的地方。 ? 滑入默认元素。 您需要在调用 (decimal) 转换之前执行此操作:

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

正如我所说,虽然这可行,但我不确定您应该执行此操作。 YMMV。

You can use the ?? operator to write this a bit more cleanly, but I'm not sure that you should ...

Element() returns null of there is no child element with that name, so that's where you could use ?? to slide in a default element. You need to do this prior to the invocation of the (decimal) cast:

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

Like I said though, while this will work, I'm not sure that you should do this. YMMV.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文