【发布时间】:2014-07-30 18:04:02
【问题描述】:
因此,众所周知,臭名昭著的NullReferenceException 是软件产品中最常见的例外。我一直在阅读一些文章,发现自己采用 Optional 方法。
其目的是围绕可空值创建某种封装
public sealed class Optional<T> where T : class {
private T value;
private Optional(T value) {
this.value = value;
}
//Used to create an empty container
public static Optional<T> Empty() {
return new Optional(null);
}
//Used to create a container with a non-null value
public static Optional<T> For(T value) {
return new Optional(value);
}
//Used to check if the container holds a non-null value
public bool IsPresent {
get { return value != null; }
}
//Retrieves the non-null value
public T Value {
get { return value; }
}
}
之后,现在的可选值可以这样返回:
public Optional<ICustomer> FindCustomerByName(string name)
{
ICustomer customer = null;
// Code to find the customer in database
if(customer != null) {
return Optional.Of(customer);
} else {
return Optional.Empty();
}
}
并像这样处理:
Optional<ICustomer> optionalCustomer = repository.FindCustomerByName("Matt");
if(optionalCustomer.IsPresent) {
ICustomer foundCustomer = optionalCustomer.Value;
Console.WriteLine("Customer found: " + customer.ToString());
} else {
Console.WriteLine("Customer not found");
}
我没有看到任何改进,只是改变了复杂性。
程序员必须记住检查值是否为IsPresent,就像他必须记住检查是否为value != null。
如果他忘记了,他会在这两种方法中得到NullReferenceException。
我错过了什么?与 Nullable<T> 和 null 合并运算符相比,Optional 模式有哪些优势(如果有)?
【问题讨论】:
-
优点是可读性。如果您觉得代码更好理解,请使用该方法。有时,空检查会让开发人员感到害怕,并将其包裹在检查中以防万一,但是如果您有明显故意的 Optional
.. customer.IsPresent,则可能更容易遵循。 -
这段代码就像一半 Java 和一半 C#,在任何一种语言中都会出现许多编译错误...
-
我不同意@Hammerstein。我发现包装器的可读性远低于直接使用
!= null。对于发现此类错误,我更倾向于使用 ReSharper 之类的工具,它可以执行代码分析来查找问题。这允许装饰方法可能返回null并带有指示此类的属性。我确信还有其他工具以类似的方式工作。另一种选择是使用Try...方法,例如Dictionary.TryGetValue。 -
您在此处介绍的内容没有任何优势 - 使用
Option/Maybe的全部意义在于您无需检查值是否存在。为此,您可以定义return\map\bind运算符,然后要求客户端在尝试解压缩内部值时必须提供默认值。您也不会将T限制为引用类型,而是统一对待T的所有可能类型。 -
LOL java.... 我已经用 C# 编码多年了,我得到的
NullReferenceExceptions 的数量可以用右手的手指数出来。完全同意@JohnSaunders,找到并修复该死的错误,而不是创建无穷无尽的抽象和模式来隐藏它。
标签: c# design-patterns nullpointerexception nullreferenceexception optional