Objective-C - !!BOOL 有益吗?

13

我正在查看另一个开发者提交的项目差异,他们有很多代码使用!!<some BOOL value>。实际上,这似乎是他们实现布尔类型getter和setter的标准模式。他们的代码实现方式如下:

- (BOOL) hasId {
    return !!hasId_;
}
- (void) setHasId:(BOOL) value {
    hasId_ = !!value;
}

我以前从未见过这种模式,想知道使用它是否有任何好处。这个双重否定有什么用吗?


我曾经见过这种情况是因为某个类没有直接转换为布尔类型的简单方法,所以他们无法使用 if(myInstance),但是它重载了一元运算符 !,所以他们会使用 if(!!myInstance)。但就你的情况而言,我不知道。 - filipe
看起来这是一个 ProtoBuf 生成的源代码。 - Richard Topchii
5个回答

12

双重布尔运算符只是确保返回的值为1或0。就是这样: )


5
这段代码可以防止像obj.hasId = 42; if (obj.hasId == YES)这样的代码失败。从技术上讲,YES(目前)被映射为1,因此整数值不同。但从概念上讲,42和YES都表示真布尔值。双重否定将42赋值折叠为YES赋值。 - user557219
谢谢,我猜想可能是这样的。但是以那种方式做有用吗?有没有避免潜在错误的可能性?比如,在进行类似于if (obj.hasId == YES)的比较时,这样做是否可以避免意外错误?虽然这样的比较本来就不太好的风格,对吧?编辑:算了,Bavarious已经提到了这一点。 - aroth
是的,但有时将其转换为1或0确实很有帮助,例如SQLite仅将布尔字段保存为1或0。 - citizen conn
7
@Bavarious 的话,但如果这么防守的话,至少让这个该死的东西可读一点; return _boolVar ? YES : NO; - bbum

3

! 是一个逻辑非运算符。因此,如果传递 setHasId:,例如 0x2,那么双重否定将存储为 0x1。


1

这相当于:

hasId_ = value ? 1 : 0;

在某些情况下,这是有用的,因为如果你这样做:

BOOL x = y & MY_FLAG;

如果设置了MY_FLAG,可能会得到0,因为结果被截断为BOOL(8位)的大小。这是意外的。出于同样的原因,有时人们更喜欢BOOL是0或1(所以比特运算与预期相符)。通常这是不必要的。

在具有内置bool类型的语言中,例如C(自C99起)和C++,将整数转换为bool会自动执行此操作。


0

在某些情况下,这是更有意义的,例如当您返回BOOL但不想使用if语句时。

- (BOOL)isMyVarSet
{
    return !!myVar;
}

在这种情况下,我不能只返回myVar,因为它不是一个BOOL(这是一个非常牵强的例子 - 我无法从我的项目中挖出一个像样的例子)。

0
我以前用过这个,我相信: if (!!myVar) 等同于: if (myVar != nil) 基本上,我用它来验证SOMETHING的值。
我承认...这可能不是实现此目标的最佳实践或最理解的方式。

区别在于:(myVar != nil)非常明显,而 (!!myVar)则会让你停下来,你必须仔细思考它的作用,然后你必须更加努力地思考,以确定编写它的人是否真正意味着它。最好清楚地表达你的意思。 - gnasher729
完全同意!我的回答已经有3年了,而且我绝对不会在任何新代码中写!!var! - mbm29414

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接