例外的三元运算符?其他选择
本文关键字:运算符 三元 其他 选择 | 更新日期: 2023-09-27 18:11:36
>假设我们有一个给定的 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;
}
但是,据我所知,没有为简化这样的事情定义运算符,考虑到可能的复杂性,我想这是有充分理由的。我想知道,有没有办法让这种事情更简洁?也许涉及monads的解决方案会起作用,或者也许这段代码应该保持原样。
我个人的猜测是,这样的运算符不适用于例外,因为它可能会鼓励不良的编码习惯。回顾以下最佳实践准则:
- 代码不应以静默方式失败,并且
- 只有在特殊情况下才应引发异常。
由于这些要点,您不应该经常需要异常处理(例如TryParse
在这里有很大帮助的方法(,除了应用程序的顶级 UI 级别,您可以在其中捕获并记录所有内容。
在您的示例中,如果 TCP 连接断开,算法通常无论如何都无法继续,那么为什么不让套接字异常冒泡到 UI 层,在那里它被捕获并向用户显示一条有用的消息("连接丢失,请检查您的 Internet 连接。{异常详细信息}"(,而不是只是返回并静默地将某些内容记录到控制台,让用户想知道为什么他的操作没有完成?
从这里: 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 实际上是对象(。作为参数,此方法采用一个函数来定义链中的下一个值。如果我们传递了空,我们得到空。让我们使用此方法重写第一个示例:
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
,则返回默认值。
在这个页面中(那是将我指向另一个页面的那个(,它首先在一个人的愿望清单中,他称之为Null Safe Dereferencing
。
有一个空对象模式的概念,我曾经成功使用过。也许这对你也有帮助。引用:
在面向对象的计算机编程中,空对象是一个对象 具有定义的中性("空"(行为。
换句话说,您不是返回null
而是返回一个定义良好的对象,该对象充当"null 对象",因此访问它不会引发异常。
另外,请参阅此谷歌搜索以获取更多示例。