The question is if thats actually desireable, as it may hide errors (use after free, use of uninitialized variable, etc.).
I see you point, but I have two reasons why it would be a good solution:
First, as in my example, if I have a bunch of variable number of items (can be anything from class instances to simple integers), I need to store them somewhere. The simple way is to put them into a dynamic array. There, if the array does not exist, it is equivalent to having zero elements in it, so, as in the example, the iterator works. If the items are regularly deleted, added and the number of them is large, then it is not too economic to move all items in the array when one is removed. So then a linked list is better, like tFPGObjectList. It seems logic that it works the same way. (When I changed from the array kind of implementation to the object list, I - incorrectly - also assumed it.)
Second, from a human point of view, what does it mean to have a code like
for C in Cs do
DoSomething(C);
?
For me it means that for all the elements that are stored in Cs we should do something. If Cs does not exist at all then obviously there are no elements in it, so there is no item to do something with. It is not necessarily an error. It is more a question of implementation.
Actually in my example Cs is a member of a class instance, where the class instance also has many siblings (other instances of the same class) also stored in an object list. Similarly to Cs for every instance I have Ds, Es, etc. When I create the instance X, it has got no C, D, or E items. There are three ways to handle it:
- Create Cs, Ds, Es, like
and then the iterator would not fail, but I feel it an overkill, when most of the time X has no Cs, Ds, or Es, so why to create class instances in the heap for nothing.
- Set Cs, Ds, Es := nil and when I want to go through all elements, before using the iterator, I do the
check. It works but seems an unnecessary extra step that could be included in the original class.
- Set them to nil (as above) and check it in the iterator. It can be done by the developer (this is why I raised it here), or it could be done somewhere during the specialization, but as I see from Warfley's elegant solution it is not even in tFPGObjectList, but in tFPGListEnumerator, what would not be that easy to do.