例外的三元运算符?其他选择?

时间:2011-10-16 07:36:08

标签: c# exception exception-handling monads ternary-operator

假设我们有一个Person类型的给定对象,并希望将其Name属性存储到局部变量中,同时如果对象为null则避免可能的异常,我们可以这样做:

string personName = null;

if (person != null)
{
    personName = person.Name;
}

但是,必须将变量声明在if语句的范围之外并将其初始化为默认值有点麻烦。相反,我们可以使用条件三元运算符来编写它:

string personName = person != null ? person.Name : null;

处理try-catch语句时存在同样的问题。假设我们试图找到TcpClient的远程地址。我们可能会这样做:

string remoteAddress = null;

try
{
    remoteAddress = tcpClient.Client.RemoteEndPoint.ToString();
}
catch (SocketException e)
{
    Console.WriteLine(e.Message);

    return;
}

然而,据我所知,没有为简化这样的事情定义运算符,我想有充分的理由,考虑到可能的复杂性。我想知道,有没有办法让这类事情更简洁?也许涉及monad的解决方案可能会起作用,或者这些代码可能保持不变。

3 个答案:

答案 0 :(得分:2)

从这里开始:http://devtalk.net/csharp/chained-null-checks-and-the-maybe-monad/

public static TResult With<TInput, TResult>(this TInput o, 
                                            Func<TInput, TResult> evaluator)
    where TResult : class where TInput : class
{
    if (o == null) return null;
    return evaluator(o);
}

上述方法可以附加到任何类型(因为TInput实际上是对象)。作为参数,此方法采用定义链中下一个值的函数。如果我们传递null,我们将返回null。让我们用这个方法重写我们的第一个例子:

string postCode = this.With(x => person)
                      .With(x => x.Address)
                      .With(x => x.PostCode);

这对于“通常”构建的对象:

var person = new { Address = new { PostCode = "12345" } };

但可以有personAddress null。我将在同一页面中添加Result扩展方法,如果“主要”值为null,则返回默认值。

this页面(那是指向另一方的那个页面),它首先出现在一个人的愿望清单中,他称之为Null Safe Dereferencing

答案 1 :(得分:2)

我个人的猜测是,这样的运营商不能用于例外,因为它可能会鼓励不良的编码习惯。回顾以下最佳实践指南:

  1. 代码不应无声地失败
  2. 只应在特殊情况下抛出异常
  3. 由于这些要点,您不应经常需要异常处理(TryParse等方法在这里有很多帮助),除了应用程序的顶级UI级别,你在那里捕获并记录所有内容。

    在您的示例中,如果TCP连接中断,算法通常无法继续,那么为什么不让套接字异常冒泡到UI层,捕获它并向用户显示有用的消息(“连接丢失,请检查您的Internet连接。{Exception Details}“),而不是仅返回并静默地将某些内容记录到控制台,让用户想知道为什么他的操作没有完成?

答案 2 :(得分:0)

我曾经成功使用了Null Object Pattern的概念。也许这对你也有帮助。引用:

  

在面向对象的计算机编程中,Null对象是一个对象   定义中性(“null”)行为。

换句话说,不是返回null而是返回一个定义良好的对象,该对象充当“空对象”,因此访问它不会引发异常。

另外,see this Google search了解更多示例。