这比Null Coalesce运算符更好吗?

sur*_*asb 2 c# linq null expression-trees

我今天遇到了这篇博客文章.

我会总结一下.这位博客正在评论这段代码并说它很难看.

// var line1 = person.Address.Lines.Line1 ?? string.Empty;
// throws NullReferenceException: 
//    {"Object reference not set to an instance of an object."}

// The ugly alternative

var line1 = person.Address == null
    ? "n/a"
    : person.Address.Lines == null
    ? "n/a"
    : person.Address.Lines.Line1;
Run Code Online (Sandbox Code Playgroud)

然后,博主继续编写一个类,允许您使用新语法替换上面的代码.

var line2 = Dis.OrDat<string>(() => person.Address.Lines.Line2, "n/a");
Run Code Online (Sandbox Code Playgroud)

Class Dis的代码如下.

 public static class Dis
  {
    public static T OrDat<T>(Expression<Func<T>> expr, T dat)
    {
      try
      {
        var func = expr.Compile();
        var result = func.Invoke();
        return result ?? dat; //now we can coalesce
      }
      catch (NullReferenceException)
      {
        return dat;
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

所以我的第一个问题是为什么包含原始代码??必须用被诅咒的?:代码替换.

我的第二个问题是为什么在Null Coalesce上使用表达式树?我能想到它的唯一原因是因为它们正在使用延迟初始化,但是从帖子中看不清楚,也没有从博客帖子中的测试代码中看出来.我也会在这里发布.

顺便说一句,有谁知道如何创建一个固定大小的代码块窗口?或者这是一个非滚动的代码块?我在Meta博客中没有看到任何内容.

haz*_*zik 6

我没有看到任何理由在博客样本中使用表达式树,Func就足够了.

我的建议是使用Maybe*monad iplementation而不是代码.见例子.

public static class Maybe
{
    public static TResult With<T, TResult>(this T self, Func<T, TResult> func) where T : class
    {
        if (self != null)
            return func(self);
        return default(TResult);
    }

    public static TResult Return<T, TResult>(this T self, Func<T, TResult> func, TResult result) where T : class
    {
        if (self != null)
            return func(self);
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

你的代码变成了:

var line2 = person
   .With(p => p.Address)
   .With(a => a.Lines)
   .Return(l => l.Line2, "n/a");
Run Code Online (Sandbox Code Playgroud)

[*]这不是真正的monad,而是一个非常简化的版本.