好的,所以我有一个方法,它以NSString
作为输入,对该字符串的内容进行操作,并返回已处理的字符串。所以宣言是:
- (NSString *) processString: (NSString *) str;
问题:我应该只返回我用作“工作”缓冲区的NSMutableString
实例,还是应该在可变项缓冲区周围创建一个新的NSString
,然后返回?
我应该这样做:
- (NSString *) processString: (NSString *) str
{
NSMutableString *work = [NSMutableString stringWithString: str];
// process 'work'
return work;
}
或者这个:
- (NSString *) processString: (NSString *) str
{
NSMutableString *work = [NSMutableString stringWithString: str];
// process 'work'
return [NSString stringWithString: work]; // or [work stringValue]?
}
第二个创建了我正在返回的字符串的另一个副本,除非NSString
执行像copy-on-modify这样的智能操作。但第一个是返回一些调用者可以在理论上稍后进行修改的东西。我不在乎他们是否这样做,因为弦是他们的。但是,是否有正当理由选择后一种形式而不是前者呢?并且,stringWithString
或stringValue
优先于另一个吗?
答案 0 :(得分:7)
完全取决于你需要的防守程度。
您的代码的客户端没有合理的方法可以测试可变性。因此,没有合理的方法客户端可以从NSString
转换为NSMutableString
并突然实现字符串的无编译器警告可变性。
因此,只要您信任您的客户,您也可以返回可变字符串(作为NSString
)。即使客户端做了一些愚蠢的事情并且改变它,编译器警告也会被诅咒,没有任何破坏。
重要的地方是你返回一些不应该在外部变异的对象的可变后备存储。在这种情况下,客户端可能会忽略编译器警告和/或强制转换为可变变量并完全bork您的对象。
或者,更巧妙的是,客户端可能会获取对所谓的不可变返回类型的引用并保持足够长的时间以使其稍后发生变异,从而使其引用处于令人惊讶的状态。
最佳实践:在计算并返回瞬态值时,可变性无关紧要。返回对内部可变商店的引用时,最好制作不可变副本。