C# c语言中的空安全导航#

C# c语言中的空安全导航#,c#,.net,linq,null,C#,.net,Linq,Null,可能的重复项: 在我的XML处理项目中,我必须浏览链接属性以获得所需的值。e、 g,obj1.obj2.obj3.obj4.obj…值。这个链中的任何对象都可能为空 我在谷歌上搜索了“c#中的NullSafe导航”,并找到了一些不错的文章。从一个例子中,我想到了实现自定义扩展。 现在我有一个关于这个扩展的性能的问题。 我有这三种解决方案。有人能告诉我哪一个是最好的选择(就性能而言) 选项1(使用): 备选案文3: //with try-catch.. With lowest cyclom

可能的重复项:

在我的XML处理项目中,我必须浏览链接属性以获得所需的值。e、 g,
obj1.obj2.obj3.obj4.obj…值
。这个链中的任何对象都可能为空

我在谷歌上搜索了“c#中的NullSafe导航”,并找到了一些不错的文章。从一个例子中,我想到了实现自定义扩展。 现在我有一个关于这个扩展的性能的问题。 我有这三种解决方案。有人能告诉我哪一个是最好的选择(就性能而言)

  • 选项1(使用):

  • 备选案文3:

    //with try-catch.. With lowest cyclomatic complexity, but not a right approach.
    try
    {
        string x = obj1.obj2.obj3.obnj4.obj5.Value;
    }
    catch(NullReferenceException ne)
    {
        //ignore exception
    }
    

我绝对不会选择“尝试捕捉”选项。这不仅是一种代码气味(异常驱动的开发),而且如果您担心性能,那么异常处理不是一种好办法

我不太明白第二种选择。您是否必须将其放在要访问Value属性的任何位置?或者是在一个扩展方法中

选项一看起来最干净

关于性能:我认为您不会发现选项1和选项2之间有太大的差异,但您可以在一个小的控制台项目中尝试一下。只需运行第一个和第二个选项,比如1000次,然后计算所需的时间。不是精确的科学,但通常足以测量性能差异

我猜你不会看到很大的不同。我想你在练习。除非你打算在一个非常重要的系统上运行,否则就使用你认为最优雅的解决方案。

我支持选项2

选项#1:如果Obj1为null,则每次都会继续检查Obj2、Obj3、Obj4和Obj5的null!至少对于选项#2,只要发现Obj1为null,它就不必检查if语句的其余部分——这意味着处理周期更少

选项3当然不好。捕获异常是一项开销,如果你反复经历数千个节点,你会感觉到它的存在——更不用说气味了

我担心的是你可能问错了问题。如果你说你在使用XML,那么这些对象实际上就是元素,对吗


如果您的问题措辞不同,并提供了有关XML文档结构的更多信息,那么我们可以编写一个Linq查询来提取值,而不需要所有硬编码的空检查(以及我假设您也在使用的循环)。

我会使用节点结构,这样您就可以执行以下操作:

var hasNullValue = false;
var x = string.Empty;
var node = firstNode;

while (node.Child != null)
{
    // On the first hit we set the null flag
    // and break out of the loop
    if (node.Value == null)
    {
        hasNullvalue = true;
        break;
    }

    node = node.Child;
}

if (!hasNullValue)
    x = node.Value;

你确定选项2很糟糕吗? try/catch块不影响性能,只要catch块不向调用方抛出任何异常(它是异常抛出机制,是性能食客)

以下是一段引文:

寻找和设计 异常严重的代码可能导致 出色的表现赢得了比赛。记住 这与try/catch无关 积木:你只有在 实际的异常被抛出。你 可以使用尽可能多的try/catch块 你想要的。使用异常 你的损失是无偿的 演出例如,你应该 远离像使用 控制流的例外情况

取自

显然,只要在链式设计#1中的某个地方找到空值,设计#3就可以防止继续求值,同时也可以防止像设计#2那样编写繁重而笨拙的代码


我认为try/catch设计值得考虑…

当它不正常时,其中一个obj对象为null,那么使用try-catch就完全可以了。顺便说一句,这只是一个可能有效也可能无效的想法,如果你做了一个扩展,它接受一个参数,然后把所有的东西都扔进去,然后在那里实现一个快速的逻辑级联逻辑呢?@Arsen:你提供的答案已经被关闭为dup,子答案也被标记为dup。@ArsenMkrt不。这不是那篇文章的重复。我已经看过了那个帖子,但它并没有讨论性能。而我的问题是关于性能。谢谢。@abatishchev,是的,这篇文章很有帮助。不幸的是,它并没有和我的谷歌搜索一起出现。:)感谢您的提及。请参阅选项1,该选项不会抛出NRE
obj1.IfNotNull(arg)
将编译为静态方法调用
Option1StaticClass.IfNotNull(obj1,arg)
。这就是为什么在空集合上使用Linq方法时,会得到ArgumentNullException而不是NRE。谢谢Patrick,你是对的。我相应地更新了我的答案。这是假设obj1、obj2、obj3等都是同一类型的,但情况可能并非如此。。。
//with try-catch.. With lowest cyclomatic complexity, but not a right approach.
try
{
    string x = obj1.obj2.obj3.obnj4.obj5.Value;
}
catch(NullReferenceException ne)
{
    //ignore exception
}
var hasNullValue = false;
var x = string.Empty;
var node = firstNode;

while (node.Child != null)
{
    // On the first hit we set the null flag
    // and break out of the loop
    if (node.Value == null)
    {
        hasNullvalue = true;
        break;
    }

    node = node.Child;
}

if (!hasNullValue)
    x = node.Value;