给定 nil 参数时要做啥的 Objective-c 约定?

Posted

技术标签:

【中文标题】给定 nil 参数时要做啥的 Objective-c 约定?【英文标题】:Objective-c convention for what to do when given nil arguments?给定 nil 参数时要做什么的 Objective-c 约定? 【发布时间】:2013-09-07 19:50:46 【问题描述】:

在 Objective-c 中,nil 预计会传播而不是导致立即失败。向 nil 发送消息(基本上)总是导致 nil。发送 nil 参数时是否有类似的期望,而这没有意义?

我想到的特殊情况本质上是函数式map 方法:

-(NSArray*) map:(id (^)(id item))projection 
    if (projection == nil) 
        // ?? what to do ??
        // throw exception?
        // return nil?
        // return empty array?
    

    NSMutableArray* r = [NSMutableArray arrayWithCapacity:[self count]];
    for (id e in self) 
        [r addObject:projection(e)];
    
    return r;

是否应该传递一个 nil 块进行投影会导致某种失败或某种默认结果?

我个人的偏好是快速失败,但我看到 Objective-C 在许多地方都倾向于不做任何事情。对于这种情况下的预期约定,我将不胜感激。

编辑

更具体地说,这样做是否可以接受:

#define require(expr) \
    if (!(expr)) \
        @throw([NSException exceptionWithName:NSInvalidArgumentException \
                                       reason:[NSString stringWithFormat:@"!require(%@)", (@#expr)] \
                                     userInfo:nil])

-(NSArray*) map:(id (^)(id item))projection 
    require(projection != nil);
    ...

【问题讨论】:

通常,如果 nil 不是一个有意义的输入(即方法参数不是可选的,而是必需的,或者必须始终是一个有效的对象等),那么 Cocoa 类通常做的是 1. 他们通过nil 或 2. 他们抛出一个NSInvalidArgumentException 时忽略错误检查和只是段错误。 我倾向于段错误。生成的崩溃跟踪比未捕获的异常有用得多。 【参考方案1】:

一般来说,如果你的方法要求某个参数不为nil,你最好尽快退出以防万一。

考虑到这一点

NSParameterAssert(item)

是一个很好的做法。对here 进行了彻底的解释,但简要总结一下,如果断言不满足,它会抛出NSInternalInconsistencyException

请注意,默认情况下 NSParameterAssert 宏(以及所有其他类似 NSAssert 的宏)在发布版本中被删除,除非您取消定义 NS_BLOCK_ASSERTIONS

here 解释了有关该主题的更多信息。

【讨论】:

【参考方案2】:

由于projection 是一个块,而不是一个对象,你不能忽略检查它是否为零;您必须进行检查并根据需要做出反应。如果该反应意味着抛出异常、返回 nil 或其他内容,这取决于您。

【讨论】:

但这就是问题所在。更好的反应是什么?抛出异常,返回nil,或者别的什么。 这里真的没有任何“更好的反应”;这只是你想做的事情......最适合你添加代码的环境。

以上是关于给定 nil 参数时要做啥的 Objective-c 约定?的主要内容,如果未能解决你的问题,请参考以下文章

bind_param() 中的第一个参数究竟是做啥的?

mfc中的settimer函数是做啥的里面的参数呢

sklearn.SVC 中的独立 SVC 行是做啥的?

Python、Scikit-learn、K-means:参数 n_init 实际上是做啥的? [复制]

刚开始接触深度学习,请问matlab里的deeplearntoolbox用来做啥的?

Keras 的 ImageDataGenerator 中的剪切究竟是做啥的?