当返回值是不可变对象时,返回可变对象是不好的做法吗?

时间:2012-09-12 17:25:04

标签: objective-c nsdictionary immutability nsmutabledictionary

如果我有这个方法:

+ (NSDictionary *)dictionaryFromQueryString:(NSString *)queryString
{
    NSMutableDictionary *this = [[NSMutableDictionary alloc] init];

    NSArray *fields = [queryString componentsSeparatedByString:@"&"];

    for(NSString *field in fields)
    {
        NSArray *fieldParts = [field componentsSeparatedByString:@"="];

        NSString *value = @"";

        if(fieldParts.count > 1)
        {
            value = [[fieldParts subarrayWithRange:NSMakeRange(1, fieldParts.count - 1)] componentsJoinedByString:@"="];
        }

        [this setObject:unescape(value) forKey:unescape(fieldParts[0])];
    }

    return this;
}

这是不好的做法,我返回NSMutableDictionary而不是NSDictionary

我应该使用NSDictionary将其转换为return [this copy];吗?

3 个答案:

答案 0 :(得分:5)

取决于。

Sergio的回答是正确的,除了一个非常重要的问题:

当包含可变字典的对象在另一个对象检索字典后改变字典时会发生什么?除非专门编写其他对象以支持字典可能发生变异的可能性,否则另一个对象现在将处于不一致状态。

鉴于copy对于字典而言是快速的,因为它是一个浅层不可变副本,通常返回副本比返回对可变版本的引用要好得多。如果你发现你的代码正在攻击制作副本的方法,那么就在对象中缓存一个不可变的副本,然后在可变的后备存储发生变化时使其无效。

答案 1 :(得分:2)

我不认为这是不好的做法。这样做的最终效果是NSDictionary的接收者不会尝试修改对象(尽管对象是可变的)。这是非常安全的,因为你的消费者方法更加通用(它可以用于可变和非可变对象),这是有道理的。

答案 2 :(得分:0)

以这种方式返回不可变对象不是真正的错误做法,因为NSMutableDictionaryNSDictionary的子类。这是多态性,因此它“一切都很好”。

但是我可能会回复这样的自动释放副本:

return [NSDictionary dictionaryWithDictionary:this];