假设我们有一个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的解决方案可能会起作用,或者这些代码可能保持不变。
答案 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" } };
但可以有person
和Address
null
。我将在同一页面中添加Result
扩展方法,如果“主要”值为null
,则返回默认值。
在this页面(那是指向另一方的那个页面),它首先出现在一个人的愿望清单中,他称之为Null Safe Dereferencing
。
答案 1 :(得分:2)
我个人的猜测是,这样的运营商不能用于例外,因为它可能会鼓励不良的编码习惯。回顾以下最佳实践指南:
由于这些要点,您不应经常需要异常处理(TryParse
等方法在这里有很多帮助),除了应用程序的顶级UI级别,你在那里捕获并记录所有内容。
在您的示例中,如果TCP连接中断,算法通常无法继续,那么为什么不让套接字异常冒泡到UI层,捕获它并向用户显示有用的消息(“连接丢失,请检查您的Internet连接。{Exception Details}“),而不是仅返回并静默地将某些内容记录到控制台,让用户想知道为什么他的操作没有完成?
答案 2 :(得分:0)
我曾经成功使用了Null Object Pattern的概念。也许这对你也有帮助。引用:
在面向对象的计算机编程中,Null对象是一个对象 定义中性(“null”)行为。
换句话说,不是返回null
而是返回一个定义良好的对象,该对象充当“空对象”,因此访问它不会引发异常。
另外,see this Google search了解更多示例。