是否有重要理由不对每个对象引用使用安全导航
本文关键字:对象引用 导航 安全 理由 是否 | 更新日期: 2023-09-27 18:33:10
我一直在向我的团队介绍一些新的 C# 语言功能 - 安全导航就是其中之一。
是否有任何重要的性能原因来避免对每个对象/属性调用使用安全导航?
例如:
myObject?.Field?.FieldValue
与。
myObject.Field.FieldValue
我知道这使得每个字段都进行空检查 - 但在紧密循环之外,这捕获的错误不值得吗? 还是鼓励懒惰编码?
编辑:
我找到了关于这个主题的整篇文章,希望对其他人有帮助!
难道这个抓到的虫子不值得吗?
恰恰相反:在任何地方应用安全导航会隐藏错误,而不是捕获它们。
错误地导航null
引用是实现中的一个错误,它可能意味着以下两件事之一:
- 您导航的字段不应
null
- 您忘了
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);