为什么可空的显式转换LINQ运算符会在空值上抛出无效的格式异常?

Joh*_*win 6 c# linq linq-to-sql

首先,我知道这个问题可以通过一个简单的响应回答,即空字符串不是空值.此外,我最近才通过另一个stackoverflow问题在今年早些时候发现了演员操作员,并且没有很多经验.即使如此,当与空合并运算符结合使用时,这些转换运算符并不完全那么简单的原因被称为处理LINQ表达式中缺少元素或属性等错误条件的优雅解决方案.我开始使用由ScottH中描述的方法"提高LINQ代码味道......",并通过ScottGu "空合并运算符(和使用它与LINQ)",以此来防范无效/缺失数据以简洁和半优雅时尚.从我可以收集的内容看来,似乎是将所有转换重载放在LINQ类中的动机之一.

因此,在我看来,处理缺失值的用例与处理空值并不完全不同,在链接文章中,这种方法被认为是处理这种情况的好方法.

场景:

int length = (int?)elem.Attribute("Length") ?? 0;
Run Code Online (Sandbox Code Playgroud)

如果缺少@Length属性,则强制转换为空值并且?运算符返回0;

如果@Length属性存在但是为空,则转换内部在int.tryparse上分支并抛出格式异常.当然对于我的用法,我希望它不会,并且只会返回null,所以我可以继续在我已经有些复杂的LINQ代码中使用这种方法.

最终,我不能提出一个解决方案,但更多的是我有兴趣听到是否有一个我错过的明显方法,或者是否有人对错失价值情景为何具有良好前景解决但空值的情况并非如此.

编辑

似乎有一些关键点我应该尝试并强调:

  • 链接的文章来自MS工作人员,我很钦佩并寻求指导.这些文章似乎提出(或至少引起注意)处理可选值的改进/替代方法

  • 在我的例子中,可选值有时以缺少元素或属性的形式出现,但元素或值的形式出现

  • 所描述的方法对于缺失值起到预期的作用,但对于空值失败

  • 遵循所描述的方法的代码似乎是在防止缺少可选值,但实际上是脆弱的并且在特定情况下中断.事实上,当你仍处于危险之中时,这就是保护的外观

  • 如果目标元素存在但是为空,则可以通过声明两个链接的示例都因运行时异常而失败来突出显示

  • 最后,似乎关键的问题是,当您签订合同(可能通过架构)时,所描述的方法非常有效,这可以确保元素或属性永远不会为空,但如果该合同不存在,则此方法无效,需要替代品

Mar*_*ell 3

我碰巧同意这种行为;如果我没有“id”属性/元素,那么我很乐意将其视为 null,但如果它存在但不解析,那就不同了 - 空字符串适用于很少的类型。您必须手动执行此操作,或者您可以在XAttribute等上添加扩展方法:

public static int? ParseInt32(this XAttribute attrib) {
    if(attrib != null && string.IsNullOrEmpty(attrib.Value)) return null;
    return (int?)attrib;
}
Run Code Online (Sandbox Code Playgroud)

请注意,我在内部使用强制转换,虽然对于 来说很简单int,但对于等来说,a.Parse将是一个不好的例子DateTime,它在 xml 中使用不同的格式,强制转换在内部处理。