5
votes

The way I understand it one of the things special about Objective C is that you can send messages to NULL and it will just ignore them instead of crashing.

Why is it that NSArray doesn't just return a NULL object if the index requested is out of bounds instead of causing a NSRangeException?

What I would expect from Objective C and NSArray is the following.

NSArray *array = [NSArray arrayWithObjects:@"Object 1", @"Object 2", @"Object 3", nil];

for (int i = 0; i < 5; i++) {
    NSString *string  = [array objectAtIndex:i];

    if (string) {
        NSLog(@"Object: %@",string);
    }
}

Allowing me to access indexes of the array with don't contain objects and simply returning NULL. Then I can check if the object exists. I can do this in other places such as checking if the object has been instantiated.

NSArray *array;

if (!array) {
    array = [NSArray array];
}

I realize this is a theory based question but I'm curious :)

2
Messaging nil is completely different than asking for an out-of-bounds index. I don't understand why you're trying to make a connection here.Lily Ballard
Because it doesn't make sense. Accessing memory outside of what your program has allocated is undefined behavior. Undefined behavior shouldn't be something a program relies upon, instead, it should be something that the program strives to remove. Now, admittedly, NSArray is not an array, but it must follow the paradigm of an array for most situations.Richard J. Ross III

2 Answers

10
votes

Messages to nil is a language level feature, not a framework API feature.

That NSArray (and other classes) throw an exception to indicate programmer error is a conscious design decision that was made when the API was designed (~1993). As both Kevin and Richard indicate, nil eats message is not erroneous in anyway whereas out of bounds is very much a case of erroneous input.

Where would you draw the line? Should substringWithRange: accept any old input? How about setObject:atIndex:?

By making NSArray @throw on bounds exceptions for indexOfObject: it makes the API consistent; any index (or range) that is out of bound will @throw.

2
votes

You could use an NSMutableDictionary to accomplish what you're trying to do. Set the keys to be NSNumber indexes. Invoking objectForKey on a nonexistent key (out of our imaginary bounds or removed) will return nil.