shim
shim

Reputation: 10116

Is it necessary or worthwhile to convert mutable NSObjects to immutable ones before returning from methods?

Say you have a method that returns an NSDictionary. To build the dictionary you may need to create an NSMutableDictionary. Is there any need or advantage to returning an immutable copy of the dictionary rather than just returning the mutable dictionary?

e.g.

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

or is it better to do the following:

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

I would think copying the dictionary, especially if it's a big one, is a waste of resources. I assume NSMutableDictionary takes up more memory, but I doubt there's a major difference. The method could return an NSMutableDictionary, but if the dictionary isn't intended to be modified after returning, why bother? The returned dictionary is an NSMutableDictionary, but the compiler would show it as an NSDictionary.

The same question applies for NSArray, NSString, etc. I haven't been able to find a similar question.

Any best practices / anything to consider?

Upvotes: 1

Views: 83

Answers (2)

psci
psci

Reputation: 933

IMO, This is a good practice to return immutable object if immutable is expected.

Consider this:

NSString *stringExpectedToBeImmutable = [NSMutableString stringWithString:@"My immutable string."];

[((NSMutableString *) stringExpectedToBeImmutable) appendString:@" Really?"];

NSLog(@"%@", stringExpectedToBeImmutable);

Someone can expect that NSString passed to method is immutable and do some computation based on this assumption, then in the middle of computation string is changing. When the computation starts the string was 20 characters long and suddenly it is 28.

This is also the reason why properties of type like NSString should be declared as copy.

This is of course some edge case but illustrate the problem pretty well.

Instead of [NSDictionary dictionaryWithDictionary:dic] you can call [dic copy]. I think copy is most efficient way to get immutable copy of mutable objects.

To conclude:

  • if you saying that you are returning immutable object, return immutable
  • if some method or API expect immutable object, give them immutable
  • use copy to get immutable version of mutable objects
  • I would not afraid of performance overhead. Premature optimization is evil :)

Upvotes: 2

Nick
Nick

Reputation: 2369

You are correct, it is typically a waste of resources and not necessary. A mutable dictionary is still a dictionary, and anyone interested in the return value of your function knows to treat it as a plain dictionary. We can thank inheritance for this.

Apple appears to follow this same advice: The return value of [NSThread callStackSymbols] is an NSArray, but if you inspect it at runtime, you will find it is an instance of NSMutableArray

Upvotes: 1

Related Questions