在从方法返回之前将可变NSObject转换为不可变的NSObject是否必要或有价值?

时间:2015-10-19 20:07:01

标签: ios objective-c nsdictionary nsmutabledictionary

假设您有一个返回NSDictionary的方法。要构建字典,您可能需要创建NSMutableDictionary。返回字典的不可变副本是否有任何需要或优势,而不仅仅是返回可变字典?

e.g。

- (NSDictionary *)doSomethingAndReturnADictionary {
    NSMutableDictionary * dic = [NSMutableDictionary new];
    // fill in dic
    return dic;
}

或者更好地执行以下操作:

- (NSDictionary *)doSomethingAndReturnADictionary {
    NSMutableDictionary * dic = [NSMutableDictionary new];
    // fill in dic
    return [NSDictionary dictionaryWithDictionary:dic];
}

我认为复制字典,特别是如果它是一个大字典,是浪费资源。我假设NSMutableDictionary占用了更多的记忆,但我怀疑这是一个主要的区别。该方法可以返回NSMutableDictionary,但如果字典在返回后不打算修改,为什么还要费心?返回的字典是NSMutableDictionary,但编译器会将其显示为NSDictionary

同样的问题适用于NSArrayNSString等。我还没有找到类似的问题。

任何最佳做法/需要考虑的事项?

2 个答案:

答案 0 :(得分:1)

你是对的,这通常是浪费资源而不是必需的。可变字典仍然是字典,任何对函数返回值感兴趣的人都知道将其视为普通字典。我们可以感谢继承。

Apple似乎遵循同样的建议: [NSThread callStackSymbols]的返回值是NSArray,但是如果在运行时检查它,您会发现它是NSMutableArray的实例

答案 1 :(得分:1)

IMO,如果需要不可变,这是一个很好的做法来返回不可变对象。

考虑一下:

function UpdateMemReasonSecond(SerNoID, sel) {
        PageMethods.UpdateSecondMemReasonUserControl(SerNoID, sel, OnUpdateSuccess, OnUpdateFailReason);
    }

有人可以预期传递给方法的NSString *stringExpectedToBeImmutable = [NSMutableString stringWithString:@"My immutable string."]; [((NSMutableString *) stringExpectedToBeImmutable) appendString:@" Really?"]; NSLog(@"%@", stringExpectedToBeImmutable); 是不可变的,并根据这个假设做一些计算,然后在计算字符串的中间正在改变。当计算开始时,字符串长度为20个字符,突然间为28个字符。

这也是类似NSString类型的属性应声明为NSString的原因。

这当然是一些优势,但很好地说明了这个问题。

您可以拨打copy而不是[NSDictionary dictionaryWithDictionary:dic]。我认为[dic copy]是获取可变对象的不可变副本的最有效方法。

总结:

  • 如果你说你要返回不可变对象,则返回immutable
  • 如果某些方法或API期望不可变对象,则给它们不可变
  • 使用copy获取可变对象的不可变版本
  • 我不怕性能开销。过早优化是邪恶的:)