有条件的去引用运算符在C#中是一件好事吗?

时间:2009-02-17 21:17:13

标签: c# language-features

在函数式语言中,通常有一个Maybe monad允许你链接对象的多个调用,并且如果链的任何部分评估,则整个表达式返回None / null什么都不是,而不是典型的NullReferenceException你通过链接一个对象可能为null的调用而进入C#。

这可以通过编写带有一些扩展方法的Maybe<T>来实现,以允许使用查询理解在C#中进行类似的行为,这在处理带有可选元素/属性的XML时非常有用。

var val = from foo in doc.Elements("foo").FirstOrDefault().ToMaybe()
          from bar in foo.Attribute("bar").ToMaybe()
          select bar.Value;

但是这种语法有点笨拙且不直观,因为人们习惯于处理Linq中的序列而不是单个元素,并且最后会留下Maybe<T>而不是T。条件去参照运算符(例如..)是否足以使其成为语言? e.g。

var val = doc.Elements("foo").FirstOrDefault()..Attribute("bar")..Value;

条件去引用将扩展为:

object val;
var foo = doc.Elements("foo").FirstOrDefault();
if (foo != null)
{
    var bar = foo.Attribute("bar");
    if (bar != null)
    {
        val = bar.Value;
    }
    else
    {
        val = null;
    }
}

我可以看到这可能会导致可怕的滥用,例如在任何地方使用..来避免NullReferenceException,但另一方面,如果使用得当,它可能在很多情况下非常方便。想法?

4 个答案:

答案 0 :(得分:1)

在对象上链接多个调用会让我害怕违反Law of Demeter。因此,我怀疑这个功能是个好主意,至少在解决您使用的具体问题方面是一个例子。

答案 1 :(得分:0)

这是一个有趣的想法,可以通过扩展方法实现。例如,这样的事情(注意,例如 - 我确信它可以改进):

public static IEnumerable<T> Maybe<T>(this IEnumerable<T> lhs, Func<IEnumerable<T>, T> rhs)
{
  if (lhs != null)
  {
    return rhs(lhs);
  }

  return lhs;
}

答案 2 :(得分:0)

我怀疑NUllable和扩展方法的组合可以实现其中的很大一部分。

这会将T限制为值类型。

(TBH我宁愿在语言中看到元组支持并消除参数,如F#所做的那样。)

您可以简化代码,将val设置为null并消除其他分支。

答案 3 :(得分:-2)

我可以看到潜在的用处,但是如果元素通常为空,那么除了轻微的性能影响之外,为什么不使用try..catch块为代码块包围NullReferenceException呢?