是否有重要理由不对每个对象引用使用安全导航

本文关键字:对象引用 导航 安全 理由 是否 | 更新日期: 2023-09-27 18:33:10

我一直在向我的团队介绍一些新的 C# 语言功能 - 安全导航就是其中之一。

是否有任何重要的性能原因来避免对每个对象/属性调用使用安全导航?

例如:

myObject?.Field?.FieldValue

与。

myObject.Field.FieldValue

我知道这使得每个字段都进行空检查 - 但在紧密循环之外,这捕获的错误不值得吗? 还是鼓励懒惰编码?

编辑:

我找到了关于这个主题的整篇文章,希望对其他人有帮助!

是否有重要理由不对每个对象引用使用安全导航

难道这个抓到的虫子不值得吗?

恰恰相反:在任何地方应用安全导航会隐藏错误,而不是捕获它们。

错误地导航null引用是实现中的一个错误,它可能意味着以下两件事之一:

  1. 您导航的字段不应null
  2. 您忘了null - 检查合法null字段

对于案例 #2,应用安全导航是一个不错的选择,因为它允许您使用更少的代码执行空检查。但是,对于情况 #1,这是一个糟糕的选择,因为它让对象或变量保持从程序逻辑的角度来看不正确的状态。

这就是为什么程序员在应用安全导航时应该使用他们的自由裁量权,单独决定每种情况。

在以下情况下不安全地导航

1(Null实际上是您正在做的事情的无效逻辑

public string ProcessHash(User user) 
{
    var hash = user?.Password?.Hash
    ...
}

它被称为安全导航不容易空检查是有原因的。想象一下,你注定要阅读上面的代码。进程哈希是否期望用户参数为空参数?如果是这样,它的 Password 属性是否也应该变为 null?你怎么知道以前的程序员是否仅仅因为他是猫王的粉丝而使用了"?."而不是"."?您必须分析整个代码才能找到答案。

2( Null 具有另一种含义,而不是代码中的不可用

盲人看到什么?黑暗?还是什么都没有?

什么是空杂货篮?

// This is a good
Basket<Grocery> basket = new Basket<Grocery>();
var count = basket.Count(); // returns 0
// This smells bad!
Basket<Grocery> basket = null
var count = basket?.Count ?? 0;

3(你正在使用?。以及作为管道操作员的扩展方法!

不要使用 ?. 将属性和方法链接在一起,因为它减少了您编写的行数并使代码很酷。 在管道后面还有很多经过深思熟虑的高级抽象,这些抽象是您在其他语言中看到的花哨的功能代码。

var resp = this.Bind<IceCreamDTO>()?.Validate()?.ToEntity()?.Insert()?.ToResponse();

上面的代码有 2 个问题。

想象一下,如果在验证绑定对象时出现错误。 你能把它的问题还给请求者吗? 好吧,你可以...但这很糟糕。

// That's not how this works. that's not how any of this works.
try 
{
    var resp = this.Bind<IceCreamDTO>()?.Validate()?.ToEntity()?.Insert()?.ToResponse();
    ...
} catch (ValidationException exp) 
{
     return exp.Errors.ToResponce();
}

在上面的示例中不太清楚(意识到这是所有方法调用而不是属性调用(,如果您将方法和属性一起导航,这也可能会破坏封装原则。

// Privacy violation
bool passwordValidation = user?.Password?.Hash?.Validate(hash);
// Property Security
bool passwordValidation = PasswordHash.Validate(user, hash);